diff options
Diffstat (limited to 'arch/mips/txx9/generic/spi_eeprom.c')
-rw-r--r-- | arch/mips/txx9/generic/spi_eeprom.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/arch/mips/txx9/generic/spi_eeprom.c b/arch/mips/txx9/generic/spi_eeprom.c new file mode 100644 index 000000000..d833dd2c9 --- /dev/null +++ b/arch/mips/txx9/generic/spi_eeprom.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * spi_eeprom.c | ||
3 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
4 | * | ||
5 | * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the | ||
6 | * terms of the GNU General Public License version 2. This program is | ||
7 | * licensed "as is" without any warranty of any kind, whether express | ||
8 | * or implied. | ||
9 | * | ||
10 | * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) | ||
11 | */ | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/export.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/spi/spi.h> | ||
17 | #include <linux/spi/eeprom.h> | ||
18 | #include <asm/txx9/spi.h> | ||
19 | |||
20 | #define AT250X0_PAGE_SIZE 8 | ||
21 | |||
22 | /* register board information for at25 driver */ | ||
23 | int __init spi_eeprom_register(int busid, int chipid, int size) | ||
24 | { | ||
25 | struct spi_board_info info = { | ||
26 | .modalias = "at25", | ||
27 | .max_speed_hz = 1500000, /* 1.5Mbps */ | ||
28 | .bus_num = busid, | ||
29 | .chip_select = chipid, | ||
30 | /* Mode 0: High-Active, Sample-Then-Shift */ | ||
31 | }; | ||
32 | struct spi_eeprom *eeprom; | ||
33 | eeprom = kzalloc(sizeof(*eeprom), GFP_KERNEL); | ||
34 | if (!eeprom) | ||
35 | return -ENOMEM; | ||
36 | strcpy(eeprom->name, "at250x0"); | ||
37 | eeprom->byte_len = size; | ||
38 | eeprom->page_size = AT250X0_PAGE_SIZE; | ||
39 | eeprom->flags = EE_ADDR1; | ||
40 | info.platform_data = eeprom; | ||
41 | return spi_register_board_info(&info, 1); | ||
42 | } | ||
43 | |||
44 | /* simple temporary spi driver to provide early access to seeprom. */ | ||
45 | |||
46 | static struct read_param { | ||
47 | int busid; | ||
48 | int chipid; | ||
49 | int address; | ||
50 | unsigned char *buf; | ||
51 | int len; | ||
52 | } *read_param; | ||
53 | |||
54 | static int __init early_seeprom_probe(struct spi_device *spi) | ||
55 | { | ||
56 | int stat = 0; | ||
57 | u8 cmd[2]; | ||
58 | int len = read_param->len; | ||
59 | char *buf = read_param->buf; | ||
60 | int address = read_param->address; | ||
61 | |||
62 | dev_info(&spi->dev, "spiclk %u KHz.\n", | ||
63 | (spi->max_speed_hz + 500) / 1000); | ||
64 | if (read_param->busid != spi->master->bus_num || | ||
65 | read_param->chipid != spi->chip_select) | ||
66 | return -ENODEV; | ||
67 | while (len > 0) { | ||
68 | /* spi_write_then_read can only work with small chunk */ | ||
69 | int c = len < AT250X0_PAGE_SIZE ? len : AT250X0_PAGE_SIZE; | ||
70 | cmd[0] = 0x03; /* AT25_READ */ | ||
71 | cmd[1] = address; | ||
72 | stat = spi_write_then_read(spi, cmd, sizeof(cmd), buf, c); | ||
73 | buf += c; | ||
74 | len -= c; | ||
75 | address += c; | ||
76 | } | ||
77 | return stat; | ||
78 | } | ||
79 | |||
80 | static struct spi_driver early_seeprom_driver __initdata = { | ||
81 | .driver = { | ||
82 | .name = "at25", | ||
83 | }, | ||
84 | .probe = early_seeprom_probe, | ||
85 | }; | ||
86 | |||
87 | int __init spi_eeprom_read(int busid, int chipid, int address, | ||
88 | unsigned char *buf, int len) | ||
89 | { | ||
90 | int ret; | ||
91 | struct read_param param = { | ||
92 | .busid = busid, | ||
93 | .chipid = chipid, | ||
94 | .address = address, | ||
95 | .buf = buf, | ||
96 | .len = len | ||
97 | }; | ||
98 | |||
99 | read_param = ¶m; | ||
100 | ret = spi_register_driver(&early_seeprom_driver); | ||
101 | if (!ret) | ||
102 | spi_unregister_driver(&early_seeprom_driver); | ||
103 | return ret; | ||
104 | } | ||