diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2008-05-30 17:27:04 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-05-30 22:18:10 -0400 |
commit | 37b5a60335305e46be93c2eb904c8b5be7aba5f6 (patch) | |
tree | 4bda528e3493a5a3a57950b37dc465e593697182 /drivers | |
parent | 9e833be3a13aa64e1f3dc50ce0ad95278212511d (diff) |
sfc: Use kernel I2C system and i2c-algo-bit driver
Remove our own implementation of I2C bit-banging.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/sfc/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/sfc/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/sfc/boards.c | 2 | ||||
-rw-r--r-- | drivers/net/sfc/boards.h | 3 | ||||
-rw-r--r-- | drivers/net/sfc/efx.c | 2 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.c | 72 | ||||
-rw-r--r-- | drivers/net/sfc/i2c-direct.c | 381 | ||||
-rw-r--r-- | drivers/net/sfc/i2c-direct.h | 91 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 11 | ||||
-rw-r--r-- | drivers/net/sfc/sfe4001.c | 126 |
10 files changed, 133 insertions, 559 deletions
diff --git a/drivers/net/sfc/Kconfig b/drivers/net/sfc/Kconfig index dbad95c295bd..3be13b592b4d 100644 --- a/drivers/net/sfc/Kconfig +++ b/drivers/net/sfc/Kconfig | |||
@@ -4,6 +4,8 @@ config SFC | |||
4 | select MII | 4 | select MII |
5 | select INET_LRO | 5 | select INET_LRO |
6 | select CRC32 | 6 | select CRC32 |
7 | select I2C | ||
8 | select I2C_ALGOBIT | ||
7 | help | 9 | help |
8 | This driver supports 10-gigabit Ethernet cards based on | 10 | This driver supports 10-gigabit Ethernet cards based on |
9 | the Solarflare Communications Solarstorm SFC4000 controller. | 11 | the Solarflare Communications Solarstorm SFC4000 controller. |
diff --git a/drivers/net/sfc/Makefile b/drivers/net/sfc/Makefile index 1d2daeec7ac1..c8f5704c8fb1 100644 --- a/drivers/net/sfc/Makefile +++ b/drivers/net/sfc/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | sfc-y += efx.o falcon.o tx.o rx.o falcon_xmac.o \ | 1 | sfc-y += efx.o falcon.o tx.o rx.o falcon_xmac.o \ |
2 | i2c-direct.o selftest.o ethtool.o xfp_phy.o \ | 2 | selftest.o ethtool.o xfp_phy.o \ |
3 | mdio_10g.o tenxpress.o boards.o sfe4001.o | 3 | mdio_10g.o tenxpress.o boards.o sfe4001.o |
4 | 4 | ||
5 | obj-$(CONFIG_SFC) += sfc.o | 5 | obj-$(CONFIG_SFC) += sfc.o |
diff --git a/drivers/net/sfc/boards.c b/drivers/net/sfc/boards.c index 7fc0328dc055..d3d3dd0a1170 100644 --- a/drivers/net/sfc/boards.c +++ b/drivers/net/sfc/boards.c | |||
@@ -109,7 +109,7 @@ static struct efx_board_data board_data[] = { | |||
109 | [EFX_BOARD_INVALID] = | 109 | [EFX_BOARD_INVALID] = |
110 | {NULL, NULL, dummy_init}, | 110 | {NULL, NULL, dummy_init}, |
111 | [EFX_BOARD_SFE4001] = | 111 | [EFX_BOARD_SFE4001] = |
112 | {"SFE4001", "10GBASE-T adapter", sfe4001_poweron}, | 112 | {"SFE4001", "10GBASE-T adapter", sfe4001_init}, |
113 | [EFX_BOARD_SFE4002] = | 113 | [EFX_BOARD_SFE4002] = |
114 | {"SFE4002", "XFP adapter", sfe4002_init}, | 114 | {"SFE4002", "XFP adapter", sfe4002_init}, |
115 | }; | 115 | }; |
diff --git a/drivers/net/sfc/boards.h b/drivers/net/sfc/boards.h index 695764dc2e64..e5e844359ce7 100644 --- a/drivers/net/sfc/boards.h +++ b/drivers/net/sfc/boards.h | |||
@@ -20,8 +20,7 @@ enum efx_board_type { | |||
20 | }; | 20 | }; |
21 | 21 | ||
22 | extern int efx_set_board_info(struct efx_nic *efx, u16 revision_info); | 22 | extern int efx_set_board_info(struct efx_nic *efx, u16 revision_info); |
23 | extern int sfe4001_poweron(struct efx_nic *efx); | 23 | extern int sfe4001_init(struct efx_nic *efx); |
24 | extern void sfe4001_poweroff(struct efx_nic *efx); | ||
25 | /* Are we putting the PHY into flash config mode */ | 24 | /* Are we putting the PHY into flash config mode */ |
26 | extern unsigned int sfe4001_phy_flash_cfg; | 25 | extern unsigned int sfe4001_phy_flash_cfg; |
27 | 26 | ||
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 449760642e31..74265d8553b8 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -1815,6 +1815,7 @@ static struct efx_board efx_dummy_board_info = { | |||
1815 | .init = efx_nic_dummy_op_int, | 1815 | .init = efx_nic_dummy_op_int, |
1816 | .init_leds = efx_port_dummy_op_int, | 1816 | .init_leds = efx_port_dummy_op_int, |
1817 | .set_fault_led = efx_port_dummy_op_blink, | 1817 | .set_fault_led = efx_port_dummy_op_blink, |
1818 | .fini = efx_port_dummy_op_void, | ||
1818 | }; | 1819 | }; |
1819 | 1820 | ||
1820 | /************************************************************************** | 1821 | /************************************************************************** |
@@ -1941,6 +1942,7 @@ static void efx_pci_remove_main(struct efx_nic *efx) | |||
1941 | efx_fini_port(efx); | 1942 | efx_fini_port(efx); |
1942 | 1943 | ||
1943 | /* Shutdown the board, then the NIC and board state */ | 1944 | /* Shutdown the board, then the NIC and board state */ |
1945 | efx->board_info.fini(efx); | ||
1944 | falcon_fini_interrupt(efx); | 1946 | falcon_fini_interrupt(efx); |
1945 | 1947 | ||
1946 | efx_fini_napi(efx); | 1948 | efx_fini_napi(efx); |
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index d3f749c72d41..8acd53de5e7c 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c | |||
@@ -13,6 +13,8 @@ | |||
13 | #include <linux/pci.h> | 13 | #include <linux/pci.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/seq_file.h> | 15 | #include <linux/seq_file.h> |
16 | #include <linux/i2c.h> | ||
17 | #include <linux/i2c-algo-bit.h> | ||
16 | #include "net_driver.h" | 18 | #include "net_driver.h" |
17 | #include "bitfield.h" | 19 | #include "bitfield.h" |
18 | #include "efx.h" | 20 | #include "efx.h" |
@@ -36,10 +38,12 @@ | |||
36 | * struct falcon_nic_data - Falcon NIC state | 38 | * struct falcon_nic_data - Falcon NIC state |
37 | * @next_buffer_table: First available buffer table id | 39 | * @next_buffer_table: First available buffer table id |
38 | * @pci_dev2: The secondary PCI device if present | 40 | * @pci_dev2: The secondary PCI device if present |
41 | * @i2c_data: Operations and state for I2C bit-bashing algorithm | ||
39 | */ | 42 | */ |
40 | struct falcon_nic_data { | 43 | struct falcon_nic_data { |
41 | unsigned next_buffer_table; | 44 | unsigned next_buffer_table; |
42 | struct pci_dev *pci_dev2; | 45 | struct pci_dev *pci_dev2; |
46 | struct i2c_algo_bit_data i2c_data; | ||
43 | }; | 47 | }; |
44 | 48 | ||
45 | /************************************************************************** | 49 | /************************************************************************** |
@@ -175,39 +179,57 @@ static inline int falcon_event_present(efx_qword_t *event) | |||
175 | * | 179 | * |
176 | ************************************************************************** | 180 | ************************************************************************** |
177 | */ | 181 | */ |
178 | static void falcon_setsdascl(struct efx_i2c_interface *i2c) | 182 | static void falcon_setsda(void *data, int state) |
179 | { | 183 | { |
184 | struct efx_nic *efx = (struct efx_nic *)data; | ||
180 | efx_oword_t reg; | 185 | efx_oword_t reg; |
181 | 186 | ||
182 | falcon_read(i2c->efx, ®, GPIO_CTL_REG_KER); | 187 | falcon_read(efx, ®, GPIO_CTL_REG_KER); |
183 | EFX_SET_OWORD_FIELD(reg, GPIO0_OEN, (i2c->scl ? 0 : 1)); | 188 | EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, !state); |
184 | EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, (i2c->sda ? 0 : 1)); | 189 | falcon_write(efx, ®, GPIO_CTL_REG_KER); |
185 | falcon_write(i2c->efx, ®, GPIO_CTL_REG_KER); | ||
186 | } | 190 | } |
187 | 191 | ||
188 | static int falcon_getsda(struct efx_i2c_interface *i2c) | 192 | static void falcon_setscl(void *data, int state) |
189 | { | 193 | { |
194 | struct efx_nic *efx = (struct efx_nic *)data; | ||
190 | efx_oword_t reg; | 195 | efx_oword_t reg; |
191 | 196 | ||
192 | falcon_read(i2c->efx, ®, GPIO_CTL_REG_KER); | 197 | falcon_read(efx, ®, GPIO_CTL_REG_KER); |
198 | EFX_SET_OWORD_FIELD(reg, GPIO0_OEN, !state); | ||
199 | falcon_write(efx, ®, GPIO_CTL_REG_KER); | ||
200 | } | ||
201 | |||
202 | static int falcon_getsda(void *data) | ||
203 | { | ||
204 | struct efx_nic *efx = (struct efx_nic *)data; | ||
205 | efx_oword_t reg; | ||
206 | |||
207 | falcon_read(efx, ®, GPIO_CTL_REG_KER); | ||
193 | return EFX_OWORD_FIELD(reg, GPIO3_IN); | 208 | return EFX_OWORD_FIELD(reg, GPIO3_IN); |
194 | } | 209 | } |
195 | 210 | ||
196 | static int falcon_getscl(struct efx_i2c_interface *i2c) | 211 | static int falcon_getscl(void *data) |
197 | { | 212 | { |
213 | struct efx_nic *efx = (struct efx_nic *)data; | ||
198 | efx_oword_t reg; | 214 | efx_oword_t reg; |
199 | 215 | ||
200 | falcon_read(i2c->efx, ®, GPIO_CTL_REG_KER); | 216 | falcon_read(efx, ®, GPIO_CTL_REG_KER); |
201 | return EFX_DWORD_FIELD(reg, GPIO0_IN); | 217 | return EFX_OWORD_FIELD(reg, GPIO0_IN); |
202 | } | 218 | } |
203 | 219 | ||
204 | static struct efx_i2c_bit_operations falcon_i2c_bit_operations = { | 220 | static struct i2c_algo_bit_data falcon_i2c_bit_operations = { |
205 | .setsda = falcon_setsdascl, | 221 | .setsda = falcon_setsda, |
206 | .setscl = falcon_setsdascl, | 222 | .setscl = falcon_setscl, |
207 | .getsda = falcon_getsda, | 223 | .getsda = falcon_getsda, |
208 | .getscl = falcon_getscl, | 224 | .getscl = falcon_getscl, |
209 | .udelay = 100, | 225 | .udelay = 100, |
210 | .mdelay = 10, | 226 | /* |
227 | * This is the number of system clock ticks after which | ||
228 | * i2c-algo-bit gives up waiting for SCL to become high. | ||
229 | * It must be at least 2 since the first tick can happen | ||
230 | * immediately after it starts waiting. | ||
231 | */ | ||
232 | .timeout = 2, | ||
211 | }; | 233 | }; |
212 | 234 | ||
213 | /************************************************************************** | 235 | /************************************************************************** |
@@ -2403,12 +2425,6 @@ int falcon_probe_nic(struct efx_nic *efx) | |||
2403 | struct falcon_nic_data *nic_data; | 2425 | struct falcon_nic_data *nic_data; |
2404 | int rc; | 2426 | int rc; |
2405 | 2427 | ||
2406 | /* Initialise I2C interface state */ | ||
2407 | efx->i2c.efx = efx; | ||
2408 | efx->i2c.op = &falcon_i2c_bit_operations; | ||
2409 | efx->i2c.sda = 1; | ||
2410 | efx->i2c.scl = 1; | ||
2411 | |||
2412 | /* Allocate storage for hardware specific data */ | 2428 | /* Allocate storage for hardware specific data */ |
2413 | nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL); | 2429 | nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL); |
2414 | efx->nic_data = nic_data; | 2430 | efx->nic_data = nic_data; |
@@ -2459,6 +2475,18 @@ int falcon_probe_nic(struct efx_nic *efx) | |||
2459 | if (rc) | 2475 | if (rc) |
2460 | goto fail5; | 2476 | goto fail5; |
2461 | 2477 | ||
2478 | /* Initialise I2C adapter */ | ||
2479 | efx->i2c_adap.owner = THIS_MODULE; | ||
2480 | efx->i2c_adap.class = I2C_CLASS_HWMON; | ||
2481 | nic_data->i2c_data = falcon_i2c_bit_operations; | ||
2482 | nic_data->i2c_data.data = efx; | ||
2483 | efx->i2c_adap.algo_data = &nic_data->i2c_data; | ||
2484 | efx->i2c_adap.dev.parent = &efx->pci_dev->dev; | ||
2485 | strcpy(efx->i2c_adap.name, "SFC4000 GPIO"); | ||
2486 | rc = i2c_bit_add_bus(&efx->i2c_adap); | ||
2487 | if (rc) | ||
2488 | goto fail5; | ||
2489 | |||
2462 | return 0; | 2490 | return 0; |
2463 | 2491 | ||
2464 | fail5: | 2492 | fail5: |
@@ -2633,6 +2661,10 @@ int falcon_init_nic(struct efx_nic *efx) | |||
2633 | void falcon_remove_nic(struct efx_nic *efx) | 2661 | void falcon_remove_nic(struct efx_nic *efx) |
2634 | { | 2662 | { |
2635 | struct falcon_nic_data *nic_data = efx->nic_data; | 2663 | struct falcon_nic_data *nic_data = efx->nic_data; |
2664 | int rc; | ||
2665 | |||
2666 | rc = i2c_del_adapter(&efx->i2c_adap); | ||
2667 | BUG_ON(rc); | ||
2636 | 2668 | ||
2637 | falcon_free_buffer(efx, &efx->irq_status); | 2669 | falcon_free_buffer(efx, &efx->irq_status); |
2638 | 2670 | ||
diff --git a/drivers/net/sfc/i2c-direct.c b/drivers/net/sfc/i2c-direct.c deleted file mode 100644 index b6c62d0ed9c2..000000000000 --- a/drivers/net/sfc/i2c-direct.c +++ /dev/null | |||
@@ -1,381 +0,0 @@ | |||
1 | /**************************************************************************** | ||
2 | * Driver for Solarflare Solarstorm network controllers and boards | ||
3 | * Copyright 2005 Fen Systems Ltd. | ||
4 | * Copyright 2006-2008 Solarflare Communications Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published | ||
8 | * by the Free Software Foundation, incorporated herein by reference. | ||
9 | */ | ||
10 | |||
11 | #include <linux/delay.h> | ||
12 | #include "net_driver.h" | ||
13 | #include "i2c-direct.h" | ||
14 | |||
15 | /* | ||
16 | * I2C data (SDA) and clock (SCL) line read/writes with appropriate | ||
17 | * delays. | ||
18 | */ | ||
19 | |||
20 | static inline void setsda(struct efx_i2c_interface *i2c, int state) | ||
21 | { | ||
22 | udelay(i2c->op->udelay); | ||
23 | i2c->sda = state; | ||
24 | i2c->op->setsda(i2c); | ||
25 | udelay(i2c->op->udelay); | ||
26 | } | ||
27 | |||
28 | static inline void setscl(struct efx_i2c_interface *i2c, int state) | ||
29 | { | ||
30 | udelay(i2c->op->udelay); | ||
31 | i2c->scl = state; | ||
32 | i2c->op->setscl(i2c); | ||
33 | udelay(i2c->op->udelay); | ||
34 | } | ||
35 | |||
36 | static inline int getsda(struct efx_i2c_interface *i2c) | ||
37 | { | ||
38 | int sda; | ||
39 | |||
40 | udelay(i2c->op->udelay); | ||
41 | sda = i2c->op->getsda(i2c); | ||
42 | udelay(i2c->op->udelay); | ||
43 | return sda; | ||
44 | } | ||
45 | |||
46 | static inline int getscl(struct efx_i2c_interface *i2c) | ||
47 | { | ||
48 | int scl; | ||
49 | |||
50 | udelay(i2c->op->udelay); | ||
51 | scl = i2c->op->getscl(i2c); | ||
52 | udelay(i2c->op->udelay); | ||
53 | return scl; | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * I2C low-level protocol operations | ||
58 | * | ||
59 | */ | ||
60 | |||
61 | static inline void i2c_release(struct efx_i2c_interface *i2c) | ||
62 | { | ||
63 | EFX_WARN_ON_PARANOID(!i2c->scl); | ||
64 | EFX_WARN_ON_PARANOID(!i2c->sda); | ||
65 | /* Devices may time out if operations do not end */ | ||
66 | setscl(i2c, 1); | ||
67 | setsda(i2c, 1); | ||
68 | EFX_BUG_ON_PARANOID(getsda(i2c) != 1); | ||
69 | EFX_BUG_ON_PARANOID(getscl(i2c) != 1); | ||
70 | } | ||
71 | |||
72 | static inline void i2c_start(struct efx_i2c_interface *i2c) | ||
73 | { | ||
74 | /* We may be restarting immediately after a {send,recv}_bit, | ||
75 | * so SCL will not necessarily already be high. | ||
76 | */ | ||
77 | EFX_WARN_ON_PARANOID(!i2c->sda); | ||
78 | setscl(i2c, 1); | ||
79 | setsda(i2c, 0); | ||
80 | setscl(i2c, 0); | ||
81 | setsda(i2c, 1); | ||
82 | } | ||
83 | |||
84 | static inline void i2c_send_bit(struct efx_i2c_interface *i2c, int bit) | ||
85 | { | ||
86 | EFX_WARN_ON_PARANOID(i2c->scl != 0); | ||
87 | setsda(i2c, bit); | ||
88 | setscl(i2c, 1); | ||
89 | setscl(i2c, 0); | ||
90 | setsda(i2c, 1); | ||
91 | } | ||
92 | |||
93 | static inline int i2c_recv_bit(struct efx_i2c_interface *i2c) | ||
94 | { | ||
95 | int bit; | ||
96 | |||
97 | EFX_WARN_ON_PARANOID(i2c->scl != 0); | ||
98 | EFX_WARN_ON_PARANOID(!i2c->sda); | ||
99 | setscl(i2c, 1); | ||
100 | bit = getsda(i2c); | ||
101 | setscl(i2c, 0); | ||
102 | return bit; | ||
103 | } | ||
104 | |||
105 | static inline void i2c_stop(struct efx_i2c_interface *i2c) | ||
106 | { | ||
107 | EFX_WARN_ON_PARANOID(i2c->scl != 0); | ||
108 | setsda(i2c, 0); | ||
109 | setscl(i2c, 1); | ||
110 | setsda(i2c, 1); | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * I2C mid-level protocol operations | ||
115 | * | ||
116 | */ | ||
117 | |||
118 | /* Sends a byte via the I2C bus and checks for an acknowledgement from | ||
119 | * the slave device. | ||
120 | */ | ||
121 | static int i2c_send_byte(struct efx_i2c_interface *i2c, u8 byte) | ||
122 | { | ||
123 | int i; | ||
124 | |||
125 | /* Send byte */ | ||
126 | for (i = 0; i < 8; i++) { | ||
127 | i2c_send_bit(i2c, !!(byte & 0x80)); | ||
128 | byte <<= 1; | ||
129 | } | ||
130 | |||
131 | /* Check for acknowledgement from slave */ | ||
132 | return (i2c_recv_bit(i2c) == 0 ? 0 : -EIO); | ||
133 | } | ||
134 | |||
135 | /* Receives a byte via the I2C bus and sends ACK/NACK to the slave device. */ | ||
136 | static u8 i2c_recv_byte(struct efx_i2c_interface *i2c, int ack) | ||
137 | { | ||
138 | u8 value = 0; | ||
139 | int i; | ||
140 | |||
141 | /* Receive byte */ | ||
142 | for (i = 0; i < 8; i++) | ||
143 | value = (value << 1) | i2c_recv_bit(i2c); | ||
144 | |||
145 | /* Send ACK/NACK */ | ||
146 | i2c_send_bit(i2c, (ack ? 0 : 1)); | ||
147 | |||
148 | return value; | ||
149 | } | ||
150 | |||
151 | /* Calculate command byte for a read operation */ | ||
152 | static inline u8 i2c_read_cmd(u8 device_id) | ||
153 | { | ||
154 | return ((device_id << 1) | 1); | ||
155 | } | ||
156 | |||
157 | /* Calculate command byte for a write operation */ | ||
158 | static inline u8 i2c_write_cmd(u8 device_id) | ||
159 | { | ||
160 | return ((device_id << 1) | 0); | ||
161 | } | ||
162 | |||
163 | int efx_i2c_check_presence(struct efx_i2c_interface *i2c, u8 device_id) | ||
164 | { | ||
165 | int rc; | ||
166 | |||
167 | /* If someone is driving the bus low we just give up. */ | ||
168 | if (getsda(i2c) == 0 || getscl(i2c) == 0) { | ||
169 | EFX_ERR(i2c->efx, "%s someone is holding the I2C bus low." | ||
170 | " Giving up.\n", __func__); | ||
171 | return -EFAULT; | ||
172 | } | ||
173 | |||
174 | /* Pretend to initiate a device write */ | ||
175 | i2c_start(i2c); | ||
176 | rc = i2c_send_byte(i2c, i2c_write_cmd(device_id)); | ||
177 | if (rc) | ||
178 | goto out; | ||
179 | |||
180 | out: | ||
181 | i2c_stop(i2c); | ||
182 | i2c_release(i2c); | ||
183 | |||
184 | return rc; | ||
185 | } | ||
186 | |||
187 | /* This performs a fast read of one or more consecutive bytes from an | ||
188 | * I2C device. Not all devices support consecutive reads of more than | ||
189 | * one byte; for these devices use efx_i2c_read() instead. | ||
190 | */ | ||
191 | int efx_i2c_fast_read(struct efx_i2c_interface *i2c, | ||
192 | u8 device_id, u8 offset, u8 *data, unsigned int len) | ||
193 | { | ||
194 | int i; | ||
195 | int rc; | ||
196 | |||
197 | EFX_WARN_ON_PARANOID(getsda(i2c) != 1); | ||
198 | EFX_WARN_ON_PARANOID(getscl(i2c) != 1); | ||
199 | EFX_WARN_ON_PARANOID(data == NULL); | ||
200 | EFX_WARN_ON_PARANOID(len < 1); | ||
201 | |||
202 | /* Select device and starting offset */ | ||
203 | i2c_start(i2c); | ||
204 | rc = i2c_send_byte(i2c, i2c_write_cmd(device_id)); | ||
205 | if (rc) | ||
206 | goto out; | ||
207 | rc = i2c_send_byte(i2c, offset); | ||
208 | if (rc) | ||
209 | goto out; | ||
210 | |||
211 | /* Read data from device */ | ||
212 | i2c_start(i2c); | ||
213 | rc = i2c_send_byte(i2c, i2c_read_cmd(device_id)); | ||
214 | if (rc) | ||
215 | goto out; | ||
216 | for (i = 0; i < (len - 1); i++) | ||
217 | /* Read and acknowledge all but the last byte */ | ||
218 | data[i] = i2c_recv_byte(i2c, 1); | ||
219 | /* Read last byte with no acknowledgement */ | ||
220 | data[i] = i2c_recv_byte(i2c, 0); | ||
221 | |||
222 | out: | ||
223 | i2c_stop(i2c); | ||
224 | i2c_release(i2c); | ||
225 | |||
226 | return rc; | ||
227 | } | ||
228 | |||
229 | /* This performs a fast write of one or more consecutive bytes to an | ||
230 | * I2C device. Not all devices support consecutive writes of more | ||
231 | * than one byte; for these devices use efx_i2c_write() instead. | ||
232 | */ | ||
233 | int efx_i2c_fast_write(struct efx_i2c_interface *i2c, | ||
234 | u8 device_id, u8 offset, | ||
235 | const u8 *data, unsigned int len) | ||
236 | { | ||
237 | int i; | ||
238 | int rc; | ||
239 | |||
240 | EFX_WARN_ON_PARANOID(getsda(i2c) != 1); | ||
241 | EFX_WARN_ON_PARANOID(getscl(i2c) != 1); | ||
242 | EFX_WARN_ON_PARANOID(len < 1); | ||
243 | |||
244 | /* Select device and starting offset */ | ||
245 | i2c_start(i2c); | ||
246 | rc = i2c_send_byte(i2c, i2c_write_cmd(device_id)); | ||
247 | if (rc) | ||
248 | goto out; | ||
249 | rc = i2c_send_byte(i2c, offset); | ||
250 | if (rc) | ||
251 | goto out; | ||
252 | |||
253 | /* Write data to device */ | ||
254 | for (i = 0; i < len; i++) { | ||
255 | rc = i2c_send_byte(i2c, data[i]); | ||
256 | if (rc) | ||
257 | goto out; | ||
258 | } | ||
259 | |||
260 | out: | ||
261 | i2c_stop(i2c); | ||
262 | i2c_release(i2c); | ||
263 | |||
264 | return rc; | ||
265 | } | ||
266 | |||
267 | /* I2C byte-by-byte read */ | ||
268 | int efx_i2c_read(struct efx_i2c_interface *i2c, | ||
269 | u8 device_id, u8 offset, u8 *data, unsigned int len) | ||
270 | { | ||
271 | int rc; | ||
272 | |||
273 | /* i2c_fast_read with length 1 is a single byte read */ | ||
274 | for (; len > 0; offset++, data++, len--) { | ||
275 | rc = efx_i2c_fast_read(i2c, device_id, offset, data, 1); | ||
276 | if (rc) | ||
277 | return rc; | ||
278 | } | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | /* I2C byte-by-byte write */ | ||
284 | int efx_i2c_write(struct efx_i2c_interface *i2c, | ||
285 | u8 device_id, u8 offset, const u8 *data, unsigned int len) | ||
286 | { | ||
287 | int rc; | ||
288 | |||
289 | /* i2c_fast_write with length 1 is a single byte write */ | ||
290 | for (; len > 0; offset++, data++, len--) { | ||
291 | rc = efx_i2c_fast_write(i2c, device_id, offset, data, 1); | ||
292 | if (rc) | ||
293 | return rc; | ||
294 | mdelay(i2c->op->mdelay); | ||
295 | } | ||
296 | |||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | |||
301 | /* This is just a slightly neater wrapper round efx_i2c_fast_write | ||
302 | * in the case where the target doesn't take an offset | ||
303 | */ | ||
304 | int efx_i2c_send_bytes(struct efx_i2c_interface *i2c, | ||
305 | u8 device_id, const u8 *data, unsigned int len) | ||
306 | { | ||
307 | return efx_i2c_fast_write(i2c, device_id, data[0], data + 1, len - 1); | ||
308 | } | ||
309 | |||
310 | /* I2C receiving of bytes - does not send an offset byte */ | ||
311 | int efx_i2c_recv_bytes(struct efx_i2c_interface *i2c, u8 device_id, | ||
312 | u8 *bytes, unsigned int len) | ||
313 | { | ||
314 | int i; | ||
315 | int rc; | ||
316 | |||
317 | EFX_WARN_ON_PARANOID(getsda(i2c) != 1); | ||
318 | EFX_WARN_ON_PARANOID(getscl(i2c) != 1); | ||
319 | EFX_WARN_ON_PARANOID(len < 1); | ||
320 | |||
321 | /* Select device */ | ||
322 | i2c_start(i2c); | ||
323 | |||
324 | /* Read data from device */ | ||
325 | rc = i2c_send_byte(i2c, i2c_read_cmd(device_id)); | ||
326 | if (rc) | ||
327 | goto out; | ||
328 | |||
329 | for (i = 0; i < (len - 1); i++) | ||
330 | /* Read and acknowledge all but the last byte */ | ||
331 | bytes[i] = i2c_recv_byte(i2c, 1); | ||
332 | /* Read last byte with no acknowledgement */ | ||
333 | bytes[i] = i2c_recv_byte(i2c, 0); | ||
334 | |||
335 | out: | ||
336 | i2c_stop(i2c); | ||
337 | i2c_release(i2c); | ||
338 | |||
339 | return rc; | ||
340 | } | ||
341 | |||
342 | /* SMBus and some I2C devices will time out if the I2C clock is | ||
343 | * held low for too long. This is most likely to happen in virtualised | ||
344 | * systems (when the entire domain is descheduled) but could in | ||
345 | * principle happen due to preemption on any busy system (and given the | ||
346 | * potential length of an I2C operation turning preemption off is not | ||
347 | * a sensible option). The following functions deal with the failure by | ||
348 | * retrying up to a fixed number of times. | ||
349 | */ | ||
350 | |||
351 | #define I2C_MAX_RETRIES (10) | ||
352 | |||
353 | /* The timeout problem will result in -EIO. If the wrapped function | ||
354 | * returns any other error, pass this up and do not retry. */ | ||
355 | #define RETRY_WRAPPER(_f) \ | ||
356 | int retries = I2C_MAX_RETRIES; \ | ||
357 | int rc; \ | ||
358 | while (retries) { \ | ||
359 | rc = _f; \ | ||
360 | if (rc != -EIO) \ | ||
361 | return rc; \ | ||
362 | retries--; \ | ||
363 | } \ | ||
364 | return rc; \ | ||
365 | |||
366 | int efx_i2c_check_presence_retry(struct efx_i2c_interface *i2c, u8 device_id) | ||
367 | { | ||
368 | RETRY_WRAPPER(efx_i2c_check_presence(i2c, device_id)) | ||
369 | } | ||
370 | |||
371 | int efx_i2c_read_retry(struct efx_i2c_interface *i2c, | ||
372 | u8 device_id, u8 offset, u8 *data, unsigned int len) | ||
373 | { | ||
374 | RETRY_WRAPPER(efx_i2c_read(i2c, device_id, offset, data, len)) | ||
375 | } | ||
376 | |||
377 | int efx_i2c_write_retry(struct efx_i2c_interface *i2c, | ||
378 | u8 device_id, u8 offset, const u8 *data, unsigned int len) | ||
379 | { | ||
380 | RETRY_WRAPPER(efx_i2c_write(i2c, device_id, offset, data, len)) | ||
381 | } | ||
diff --git a/drivers/net/sfc/i2c-direct.h b/drivers/net/sfc/i2c-direct.h deleted file mode 100644 index 291e561071f5..000000000000 --- a/drivers/net/sfc/i2c-direct.h +++ /dev/null | |||
@@ -1,91 +0,0 @@ | |||
1 | /**************************************************************************** | ||
2 | * Driver for Solarflare Solarstorm network controllers and boards | ||
3 | * Copyright 2005 Fen Systems Ltd. | ||
4 | * Copyright 2006 Solarflare Communications Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published | ||
8 | * by the Free Software Foundation, incorporated herein by reference. | ||
9 | */ | ||
10 | |||
11 | #ifndef EFX_I2C_DIRECT_H | ||
12 | #define EFX_I2C_DIRECT_H | ||
13 | |||
14 | #include "net_driver.h" | ||
15 | |||
16 | /* | ||
17 | * Direct control of an I2C bus | ||
18 | */ | ||
19 | |||
20 | struct efx_i2c_interface; | ||
21 | |||
22 | /** | ||
23 | * struct efx_i2c_bit_operations - I2C bus direct control methods | ||
24 | * | ||
25 | * I2C bus direct control methods. | ||
26 | * | ||
27 | * @setsda: Set state of SDA line | ||
28 | * @setscl: Set state of SCL line | ||
29 | * @getsda: Get state of SDA line | ||
30 | * @getscl: Get state of SCL line | ||
31 | * @udelay: Delay between each bit operation | ||
32 | * @mdelay: Delay between each byte write | ||
33 | */ | ||
34 | struct efx_i2c_bit_operations { | ||
35 | void (*setsda) (struct efx_i2c_interface *i2c); | ||
36 | void (*setscl) (struct efx_i2c_interface *i2c); | ||
37 | int (*getsda) (struct efx_i2c_interface *i2c); | ||
38 | int (*getscl) (struct efx_i2c_interface *i2c); | ||
39 | unsigned int udelay; | ||
40 | unsigned int mdelay; | ||
41 | }; | ||
42 | |||
43 | /** | ||
44 | * struct efx_i2c_interface - an I2C interface | ||
45 | * | ||
46 | * An I2C interface. | ||
47 | * | ||
48 | * @efx: Attached Efx NIC | ||
49 | * @op: I2C bus control methods | ||
50 | * @sda: Current output state of SDA line | ||
51 | * @scl: Current output state of SCL line | ||
52 | */ | ||
53 | struct efx_i2c_interface { | ||
54 | struct efx_nic *efx; | ||
55 | struct efx_i2c_bit_operations *op; | ||
56 | unsigned int sda:1; | ||
57 | unsigned int scl:1; | ||
58 | }; | ||
59 | |||
60 | extern int efx_i2c_check_presence(struct efx_i2c_interface *i2c, u8 device_id); | ||
61 | extern int efx_i2c_fast_read(struct efx_i2c_interface *i2c, | ||
62 | u8 device_id, u8 offset, | ||
63 | u8 *data, unsigned int len); | ||
64 | extern int efx_i2c_fast_write(struct efx_i2c_interface *i2c, | ||
65 | u8 device_id, u8 offset, | ||
66 | const u8 *data, unsigned int len); | ||
67 | extern int efx_i2c_read(struct efx_i2c_interface *i2c, | ||
68 | u8 device_id, u8 offset, u8 *data, unsigned int len); | ||
69 | extern int efx_i2c_write(struct efx_i2c_interface *i2c, | ||
70 | u8 device_id, u8 offset, | ||
71 | const u8 *data, unsigned int len); | ||
72 | |||
73 | extern int efx_i2c_send_bytes(struct efx_i2c_interface *i2c, u8 device_id, | ||
74 | const u8 *bytes, unsigned int len); | ||
75 | |||
76 | extern int efx_i2c_recv_bytes(struct efx_i2c_interface *i2c, u8 device_id, | ||
77 | u8 *bytes, unsigned int len); | ||
78 | |||
79 | |||
80 | /* Versions of the API that retry on failure. */ | ||
81 | extern int efx_i2c_check_presence_retry(struct efx_i2c_interface *i2c, | ||
82 | u8 device_id); | ||
83 | |||
84 | extern int efx_i2c_read_retry(struct efx_i2c_interface *i2c, | ||
85 | u8 device_id, u8 offset, u8 *data, unsigned int len); | ||
86 | |||
87 | extern int efx_i2c_write_retry(struct efx_i2c_interface *i2c, | ||
88 | u8 device_id, u8 offset, | ||
89 | const u8 *data, unsigned int len); | ||
90 | |||
91 | #endif /* EFX_I2C_DIRECT_H */ | ||
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 5e20e7551dae..d803b86c647c 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
@@ -26,10 +26,10 @@ | |||
26 | #include <linux/highmem.h> | 26 | #include <linux/highmem.h> |
27 | #include <linux/workqueue.h> | 27 | #include <linux/workqueue.h> |
28 | #include <linux/inet_lro.h> | 28 | #include <linux/inet_lro.h> |
29 | #include <linux/i2c.h> | ||
29 | 30 | ||
30 | #include "enum.h" | 31 | #include "enum.h" |
31 | #include "bitfield.h" | 32 | #include "bitfield.h" |
32 | #include "i2c-direct.h" | ||
33 | 33 | ||
34 | #define EFX_MAX_LRO_DESCRIPTORS 8 | 34 | #define EFX_MAX_LRO_DESCRIPTORS 8 |
35 | #define EFX_MAX_LRO_AGGR MAX_SKB_FRAGS | 35 | #define EFX_MAX_LRO_AGGR MAX_SKB_FRAGS |
@@ -418,7 +418,10 @@ struct efx_blinker { | |||
418 | * @init_leds: Sets up board LEDs | 418 | * @init_leds: Sets up board LEDs |
419 | * @set_fault_led: Turns the fault LED on or off | 419 | * @set_fault_led: Turns the fault LED on or off |
420 | * @blink: Starts/stops blinking | 420 | * @blink: Starts/stops blinking |
421 | * @fini: Cleanup function | ||
421 | * @blinker: used to blink LEDs in software | 422 | * @blinker: used to blink LEDs in software |
423 | * @hwmon_client: I2C client for hardware monitor | ||
424 | * @ioexp_client: I2C client for power/port control | ||
422 | */ | 425 | */ |
423 | struct efx_board { | 426 | struct efx_board { |
424 | int type; | 427 | int type; |
@@ -431,7 +434,9 @@ struct efx_board { | |||
431 | int (*init_leds)(struct efx_nic *efx); | 434 | int (*init_leds)(struct efx_nic *efx); |
432 | void (*set_fault_led) (struct efx_nic *efx, int state); | 435 | void (*set_fault_led) (struct efx_nic *efx, int state); |
433 | void (*blink) (struct efx_nic *efx, int start); | 436 | void (*blink) (struct efx_nic *efx, int start); |
437 | void (*fini) (struct efx_nic *nic); | ||
434 | struct efx_blinker blinker; | 438 | struct efx_blinker blinker; |
439 | struct i2c_client *hwmon_client, *ioexp_client; | ||
435 | }; | 440 | }; |
436 | 441 | ||
437 | #define STRING_TABLE_LOOKUP(val, member) \ | 442 | #define STRING_TABLE_LOOKUP(val, member) \ |
@@ -618,7 +623,7 @@ union efx_multicast_hash { | |||
618 | * @membase: Memory BAR value | 623 | * @membase: Memory BAR value |
619 | * @biu_lock: BIU (bus interface unit) lock | 624 | * @biu_lock: BIU (bus interface unit) lock |
620 | * @interrupt_mode: Interrupt mode | 625 | * @interrupt_mode: Interrupt mode |
621 | * @i2c: I2C interface | 626 | * @i2c_adap: I2C adapter |
622 | * @board_info: Board-level information | 627 | * @board_info: Board-level information |
623 | * @state: Device state flag. Serialised by the rtnl_lock. | 628 | * @state: Device state flag. Serialised by the rtnl_lock. |
624 | * @reset_pending: Pending reset method (normally RESET_TYPE_NONE) | 629 | * @reset_pending: Pending reset method (normally RESET_TYPE_NONE) |
@@ -686,7 +691,7 @@ struct efx_nic { | |||
686 | spinlock_t biu_lock; | 691 | spinlock_t biu_lock; |
687 | enum efx_int_mode interrupt_mode; | 692 | enum efx_int_mode interrupt_mode; |
688 | 693 | ||
689 | struct efx_i2c_interface i2c; | 694 | struct i2c_adapter i2c_adap; |
690 | struct efx_board board_info; | 695 | struct efx_board board_info; |
691 | 696 | ||
692 | enum nic_state state; | 697 | enum nic_state state; |
diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c index 66a0d1442aba..b27849523990 100644 --- a/drivers/net/sfc/sfe4001.c +++ b/drivers/net/sfc/sfe4001.c | |||
@@ -106,28 +106,27 @@ | |||
106 | 106 | ||
107 | static const u8 xgphy_max_temperature = 90; | 107 | static const u8 xgphy_max_temperature = 90; |
108 | 108 | ||
109 | void sfe4001_poweroff(struct efx_nic *efx) | 109 | static void sfe4001_poweroff(struct efx_nic *efx) |
110 | { | 110 | { |
111 | struct efx_i2c_interface *i2c = &efx->i2c; | 111 | struct i2c_client *ioexp_client = efx->board_info.ioexp_client; |
112 | struct i2c_client *hwmon_client = efx->board_info.hwmon_client; | ||
112 | 113 | ||
113 | u8 cfg, out, in; | 114 | /* Turn off all power rails and disable outputs */ |
115 | i2c_smbus_write_byte_data(ioexp_client, P0_OUT, 0xff); | ||
116 | i2c_smbus_write_byte_data(ioexp_client, P1_CONFIG, 0xff); | ||
117 | i2c_smbus_write_byte_data(ioexp_client, P0_CONFIG, 0xff); | ||
114 | 118 | ||
115 | EFX_INFO(efx, "%s\n", __func__); | 119 | /* Clear any over-temperature alert */ |
116 | 120 | i2c_smbus_read_byte_data(hwmon_client, RSL); | |
117 | /* Turn off all power rails */ | 121 | } |
118 | out = 0xff; | ||
119 | efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1); | ||
120 | |||
121 | /* Disable port 1 outputs on IO expander */ | ||
122 | cfg = 0xff; | ||
123 | efx_i2c_write(i2c, PCA9539, P1_CONFIG, &cfg, 1); | ||
124 | 122 | ||
125 | /* Disable port 0 outputs on IO expander */ | 123 | static void sfe4001_fini(struct efx_nic *efx) |
126 | cfg = 0xff; | 124 | { |
127 | efx_i2c_write(i2c, PCA9539, P0_CONFIG, &cfg, 1); | 125 | EFX_INFO(efx, "%s\n", __func__); |
128 | 126 | ||
129 | /* Clear any over-temperature alert */ | 127 | sfe4001_poweroff(efx); |
130 | efx_i2c_read(i2c, MAX6647, RSL, &in, 1); | 128 | i2c_unregister_device(efx->board_info.ioexp_client); |
129 | i2c_unregister_device(efx->board_info.hwmon_client); | ||
131 | } | 130 | } |
132 | 131 | ||
133 | /* The P0_EN_3V3X line on SFE4001 boards (from A2 onward) is connected | 132 | /* The P0_EN_3V3X line on SFE4001 boards (from A2 onward) is connected |
@@ -143,14 +142,26 @@ MODULE_PARM_DESC(phy_flash_cfg, | |||
143 | * be turned on before the PHY can be used. | 142 | * be turned on before the PHY can be used. |
144 | * Context: Process context, rtnl lock held | 143 | * Context: Process context, rtnl lock held |
145 | */ | 144 | */ |
146 | int sfe4001_poweron(struct efx_nic *efx) | 145 | int sfe4001_init(struct efx_nic *efx) |
147 | { | 146 | { |
148 | struct efx_i2c_interface *i2c = &efx->i2c; | 147 | struct i2c_client *hwmon_client, *ioexp_client; |
149 | unsigned int count; | 148 | unsigned int count; |
150 | int rc; | 149 | int rc; |
151 | u8 out, in, cfg; | 150 | u8 out; |
152 | efx_dword_t reg; | 151 | efx_dword_t reg; |
153 | 152 | ||
153 | hwmon_client = i2c_new_dummy(&efx->i2c_adap, MAX6647); | ||
154 | if (!hwmon_client) | ||
155 | return -EIO; | ||
156 | efx->board_info.hwmon_client = hwmon_client; | ||
157 | |||
158 | ioexp_client = i2c_new_dummy(&efx->i2c_adap, PCA9539); | ||
159 | if (!ioexp_client) { | ||
160 | rc = -EIO; | ||
161 | goto fail_hwmon; | ||
162 | } | ||
163 | efx->board_info.ioexp_client = ioexp_client; | ||
164 | |||
154 | /* 10Xpress has fixed-function LED pins, so there is no board-specific | 165 | /* 10Xpress has fixed-function LED pins, so there is no board-specific |
155 | * blink code. */ | 166 | * blink code. */ |
156 | efx->board_info.blink = tenxpress_phy_blink; | 167 | efx->board_info.blink = tenxpress_phy_blink; |
@@ -166,44 +177,45 @@ int sfe4001_poweron(struct efx_nic *efx) | |||
166 | falcon_xmac_writel(efx, ®, XX_PWR_RST_REG_MAC); | 177 | falcon_xmac_writel(efx, ®, XX_PWR_RST_REG_MAC); |
167 | udelay(10); | 178 | udelay(10); |
168 | 179 | ||
180 | efx->board_info.fini = sfe4001_fini; | ||
181 | |||
169 | /* Set DSP over-temperature alert threshold */ | 182 | /* Set DSP over-temperature alert threshold */ |
170 | EFX_INFO(efx, "DSP cut-out at %dC\n", xgphy_max_temperature); | 183 | EFX_INFO(efx, "DSP cut-out at %dC\n", xgphy_max_temperature); |
171 | rc = efx_i2c_write(i2c, MAX6647, WLHO, | 184 | rc = i2c_smbus_write_byte_data(hwmon_client, WLHO, |
172 | &xgphy_max_temperature, 1); | 185 | xgphy_max_temperature); |
173 | if (rc) | 186 | if (rc) |
174 | goto fail1; | 187 | goto fail_ioexp; |
175 | 188 | ||
176 | /* Read it back and verify */ | 189 | /* Read it back and verify */ |
177 | rc = efx_i2c_read(i2c, MAX6647, RLHN, &in, 1); | 190 | rc = i2c_smbus_read_byte_data(hwmon_client, RLHN); |
178 | if (rc) | 191 | if (rc < 0) |
179 | goto fail1; | 192 | goto fail_ioexp; |
180 | if (in != xgphy_max_temperature) { | 193 | if (rc != xgphy_max_temperature) { |
181 | rc = -EFAULT; | 194 | rc = -EFAULT; |
182 | goto fail1; | 195 | goto fail_ioexp; |
183 | } | 196 | } |
184 | 197 | ||
185 | /* Clear any previous over-temperature alert */ | 198 | /* Clear any previous over-temperature alert */ |
186 | rc = efx_i2c_read(i2c, MAX6647, RSL, &in, 1); | 199 | rc = i2c_smbus_read_byte_data(hwmon_client, RSL); |
187 | if (rc) | 200 | if (rc < 0) |
188 | goto fail1; | 201 | goto fail_ioexp; |
189 | 202 | ||
190 | /* Enable port 0 and port 1 outputs on IO expander */ | 203 | /* Enable port 0 and port 1 outputs on IO expander */ |
191 | cfg = 0x00; | 204 | rc = i2c_smbus_write_byte_data(ioexp_client, P0_CONFIG, 0x00); |
192 | rc = efx_i2c_write(i2c, PCA9539, P0_CONFIG, &cfg, 1); | ||
193 | if (rc) | 205 | if (rc) |
194 | goto fail1; | 206 | goto fail_ioexp; |
195 | cfg = 0xff & ~(1 << P1_SPARE_LBN); | 207 | rc = i2c_smbus_write_byte_data(ioexp_client, P1_CONFIG, |
196 | rc = efx_i2c_write(i2c, PCA9539, P1_CONFIG, &cfg, 1); | 208 | 0xff & ~(1 << P1_SPARE_LBN)); |
197 | if (rc) | 209 | if (rc) |
198 | goto fail2; | 210 | goto fail_on; |
199 | 211 | ||
200 | /* Turn all power off then wait 1 sec. This ensures PHY is reset */ | 212 | /* Turn all power off then wait 1 sec. This ensures PHY is reset */ |
201 | out = 0xff & ~((0 << P0_EN_1V2_LBN) | (0 << P0_EN_2V5_LBN) | | 213 | out = 0xff & ~((0 << P0_EN_1V2_LBN) | (0 << P0_EN_2V5_LBN) | |
202 | (0 << P0_EN_3V3X_LBN) | (0 << P0_EN_5V_LBN) | | 214 | (0 << P0_EN_3V3X_LBN) | (0 << P0_EN_5V_LBN) | |
203 | (0 << P0_EN_1V0X_LBN)); | 215 | (0 << P0_EN_1V0X_LBN)); |
204 | rc = efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1); | 216 | rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out); |
205 | if (rc) | 217 | if (rc) |
206 | goto fail3; | 218 | goto fail_on; |
207 | 219 | ||
208 | schedule_timeout_uninterruptible(HZ); | 220 | schedule_timeout_uninterruptible(HZ); |
209 | count = 0; | 221 | count = 0; |
@@ -215,26 +227,26 @@ int sfe4001_poweron(struct efx_nic *efx) | |||
215 | if (sfe4001_phy_flash_cfg) | 227 | if (sfe4001_phy_flash_cfg) |
216 | out |= 1 << P0_EN_3V3X_LBN; | 228 | out |= 1 << P0_EN_3V3X_LBN; |
217 | 229 | ||
218 | rc = efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1); | 230 | rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out); |
219 | if (rc) | 231 | if (rc) |
220 | goto fail3; | 232 | goto fail_on; |
221 | msleep(10); | 233 | msleep(10); |
222 | 234 | ||
223 | /* Turn on 1V power rail */ | 235 | /* Turn on 1V power rail */ |
224 | out &= ~(1 << P0_EN_1V0X_LBN); | 236 | out &= ~(1 << P0_EN_1V0X_LBN); |
225 | rc = efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1); | 237 | rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out); |
226 | if (rc) | 238 | if (rc) |
227 | goto fail3; | 239 | goto fail_on; |
228 | 240 | ||
229 | EFX_INFO(efx, "waiting for power (attempt %d)...\n", count); | 241 | EFX_INFO(efx, "waiting for power (attempt %d)...\n", count); |
230 | 242 | ||
231 | schedule_timeout_uninterruptible(HZ); | 243 | schedule_timeout_uninterruptible(HZ); |
232 | 244 | ||
233 | /* Check DSP is powered */ | 245 | /* Check DSP is powered */ |
234 | rc = efx_i2c_read(i2c, PCA9539, P1_IN, &in, 1); | 246 | rc = i2c_smbus_read_byte_data(ioexp_client, P1_IN); |
235 | if (rc) | 247 | if (rc < 0) |
236 | goto fail3; | 248 | goto fail_on; |
237 | if (in & (1 << P1_AFE_PWD_LBN)) | 249 | if (rc & (1 << P1_AFE_PWD_LBN)) |
238 | goto done; | 250 | goto done; |
239 | 251 | ||
240 | /* DSP doesn't look powered in flash config mode */ | 252 | /* DSP doesn't look powered in flash config mode */ |
@@ -244,23 +256,17 @@ int sfe4001_poweron(struct efx_nic *efx) | |||
244 | 256 | ||
245 | EFX_INFO(efx, "timed out waiting for power\n"); | 257 | EFX_INFO(efx, "timed out waiting for power\n"); |
246 | rc = -ETIMEDOUT; | 258 | rc = -ETIMEDOUT; |
247 | goto fail3; | 259 | goto fail_on; |
248 | 260 | ||
249 | done: | 261 | done: |
250 | EFX_INFO(efx, "PHY is powered on\n"); | 262 | EFX_INFO(efx, "PHY is powered on\n"); |
251 | return 0; | 263 | return 0; |
252 | 264 | ||
253 | fail3: | 265 | fail_on: |
254 | /* Turn off all power rails */ | 266 | sfe4001_poweroff(efx); |
255 | out = 0xff; | 267 | fail_ioexp: |
256 | efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1); | 268 | i2c_unregister_device(ioexp_client); |
257 | /* Disable port 1 outputs on IO expander */ | 269 | fail_hwmon: |
258 | out = 0xff; | 270 | i2c_unregister_device(hwmon_client); |
259 | efx_i2c_write(i2c, PCA9539, P1_CONFIG, &out, 1); | ||
260 | fail2: | ||
261 | /* Disable port 0 outputs on IO expander */ | ||
262 | out = 0xff; | ||
263 | efx_i2c_write(i2c, PCA9539, P0_CONFIG, &out, 1); | ||
264 | fail1: | ||
265 | return rc; | 271 | return rc; |
266 | } | 272 | } |