aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorSteve Glendinning <steve.glendinning@smsc.com>2008-11-04 19:35:38 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-10 18:12:45 -0500
commit2107fb8b5bf018be691afdd4c6ffaecf0c3307be (patch)
treef3554a4cb46f23a9d4de7cc54d56ad229b055236 /drivers/net
parent6fabd715e6d8e1b37c0c66d9bfda2c19643e3f77 (diff)
smsc911x: add dynamic bus configuration
Convert the driver to select 16-bit or 32-bit bus access at runtime, at a small performance cost. Signed-off-by: Steve Glendinning <steve.glendinning@smsc.com> Acked-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/smsc911x.c158
-rw-r--r--drivers/net/smsc911x.h1
2 files changed, 79 insertions, 80 deletions
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index fe517880fc97..4b8ff843e300 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -77,19 +77,16 @@ struct smsc911x_data {
77 unsigned int generation; 77 unsigned int generation;
78 78
79 /* device configuration (copied from platform_data during probe) */ 79 /* device configuration (copied from platform_data during probe) */
80 unsigned int irq_polarity; 80 struct smsc911x_platform_config config;
81 unsigned int irq_type;
82 phy_interface_t phy_interface;
83 81
84 /* This needs to be acquired before calling any of below: 82 /* This needs to be acquired before calling any of below:
85 * smsc911x_mac_read(), smsc911x_mac_write() 83 * smsc911x_mac_read(), smsc911x_mac_write()
86 */ 84 */
87 spinlock_t mac_lock; 85 spinlock_t mac_lock;
88 86
89#if (!SMSC_CAN_USE_32BIT) 87 /* spinlock to ensure 16-bit accesses are serialised.
90 /* spinlock to ensure 16-bit accesses are serialised */ 88 * unused with a 32-bit bus */
91 spinlock_t dev_lock; 89 spinlock_t dev_lock;
92#endif
93 90
94 struct phy_device *phy_dev; 91 struct phy_device *phy_dev;
95 struct mii_bus *mii_bus; 92 struct mii_bus *mii_bus;
@@ -121,70 +118,56 @@ struct smsc911x_data {
121 unsigned int hashlo; 118 unsigned int hashlo;
122}; 119};
123 120
124#if SMSC_CAN_USE_32BIT 121/* The 16-bit access functions are significantly slower, due to the locking
125
126static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg)
127{
128 return readl(pdata->ioaddr + reg);
129}
130
131static inline void smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg,
132 u32 val)
133{
134 writel(val, pdata->ioaddr + reg);
135}
136
137/* Writes a packet to the TX_DATA_FIFO */
138static inline void
139smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf,
140 unsigned int wordcount)
141{
142 writesl(pdata->ioaddr + TX_DATA_FIFO, buf, wordcount);
143}
144
145/* Reads a packet out of the RX_DATA_FIFO */
146static inline void
147smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf,
148 unsigned int wordcount)
149{
150 readsl(pdata->ioaddr + RX_DATA_FIFO, buf, wordcount);
151}
152
153#else /* SMSC_CAN_USE_32BIT */
154
155/* These 16-bit access functions are significantly slower, due to the locking
156 * necessary. If your bus hardware can be configured to do this for you 122 * necessary. If your bus hardware can be configured to do this for you
157 * (in response to a single 32-bit operation from software), you should use 123 * (in response to a single 32-bit operation from software), you should use
158 * the 32-bit access functions instead. */ 124 * the 32-bit access functions instead. */
159 125
160static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg) 126static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg)
161{ 127{
162 unsigned long flags; 128 if (pdata->config.flags & SMSC911X_USE_32BIT)
163 u32 data; 129 return readl(pdata->ioaddr + reg);
164 130
165 /* these two 16-bit reads must be performed consecutively, so must 131 if (pdata->config.flags & SMSC911X_USE_16BIT) {
166 * not be interrupted by our own ISR (which would start another 132 u32 data;
167 * read operation) */ 133 unsigned long flags;
168 spin_lock_irqsave(&pdata->dev_lock, flags); 134
169 data = ((readw(pdata->ioaddr + reg) & 0xFFFF) | 135 /* these two 16-bit reads must be performed consecutively, so
170 ((readw(pdata->ioaddr + reg + 2) & 0xFFFF) << 16)); 136 * must not be interrupted by our own ISR (which would start
171 spin_unlock_irqrestore(&pdata->dev_lock, flags); 137 * another read operation) */
138 spin_lock_irqsave(&pdata->dev_lock, flags);
139 data = ((readw(pdata->ioaddr + reg) & 0xFFFF) |
140 ((readw(pdata->ioaddr + reg + 2) & 0xFFFF) << 16));
141 spin_unlock_irqrestore(&pdata->dev_lock, flags);
142
143 return data;
144 }
172 145
173 return data; 146 BUG();
174} 147}
175 148
176static inline void smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg, 149static inline void smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg,
177 u32 val) 150 u32 val)
178{ 151{
179 unsigned long flags; 152 if (pdata->config.flags & SMSC911X_USE_32BIT) {
153 writel(val, pdata->ioaddr + reg);
154 return;
155 }
156
157 if (pdata->config.flags & SMSC911X_USE_16BIT) {
158 unsigned long flags;
159
160 /* these two 16-bit writes must be performed consecutively, so
161 * must not be interrupted by our own ISR (which would start
162 * another read operation) */
163 spin_lock_irqsave(&pdata->dev_lock, flags);
164 writew(val & 0xFFFF, pdata->ioaddr + reg);
165 writew((val >> 16) & 0xFFFF, pdata->ioaddr + reg + 2);
166 spin_unlock_irqrestore(&pdata->dev_lock, flags);
167 return;
168 }
180 169
181 /* these two 16-bit writes must be performed consecutively, so must 170 BUG();
182 * not be interrupted by our own ISR (which would start another
183 * read operation) */
184 spin_lock_irqsave(&pdata->dev_lock, flags);
185 writew(val & 0xFFFF, pdata->ioaddr + reg);
186 writew((val >> 16) & 0xFFFF, pdata->ioaddr + reg + 2);
187 spin_unlock_irqrestore(&pdata->dev_lock, flags);
188} 171}
189 172
190/* Writes a packet to the TX_DATA_FIFO */ 173/* Writes a packet to the TX_DATA_FIFO */
@@ -192,8 +175,18 @@ static inline void
192smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf, 175smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf,
193 unsigned int wordcount) 176 unsigned int wordcount)
194{ 177{
195 while (wordcount--) 178 if (pdata->config.flags & SMSC911X_USE_32BIT) {
196 smsc911x_reg_write(pdata, TX_DATA_FIFO, *buf++); 179 writesl(pdata->ioaddr + TX_DATA_FIFO, buf, wordcount);
180 return;
181 }
182
183 if (pdata->config.flags & SMSC911X_USE_16BIT) {
184 while (wordcount--)
185 smsc911x_reg_write(pdata, TX_DATA_FIFO, *buf++);
186 return;
187 }
188
189 BUG();
197} 190}
198 191
199/* Reads a packet out of the RX_DATA_FIFO */ 192/* Reads a packet out of the RX_DATA_FIFO */
@@ -201,11 +194,19 @@ static inline void
201smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf, 194smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf,
202 unsigned int wordcount) 195 unsigned int wordcount)
203{ 196{
204 while (wordcount--) 197 if (pdata->config.flags & SMSC911X_USE_32BIT) {
205 *buf++ = smsc911x_reg_read(pdata, RX_DATA_FIFO); 198 readsl(pdata->ioaddr + RX_DATA_FIFO, buf, wordcount);
206} 199 return;
200 }
207 201
208#endif /* SMSC_CAN_USE_32BIT */ 202 if (pdata->config.flags & SMSC911X_USE_16BIT) {
203 while (wordcount--)
204 *buf++ = smsc911x_reg_read(pdata, RX_DATA_FIFO);
205 return;
206 }
207
208 BUG();
209}
209 210
210/* waits for MAC not busy, with timeout. Only called by smsc911x_mac_read 211/* waits for MAC not busy, with timeout. Only called by smsc911x_mac_read
211 * and smsc911x_mac_write, so assumes mac_lock is held */ 212 * and smsc911x_mac_write, so assumes mac_lock is held */
@@ -790,7 +791,7 @@ static int smsc911x_mii_probe(struct net_device *dev)
790 } 791 }
791 792
792 phydev = phy_connect(dev, phydev->dev.bus_id, 793 phydev = phy_connect(dev, phydev->dev.bus_id,
793 &smsc911x_phy_adjust_link, 0, pdata->phy_interface); 794 &smsc911x_phy_adjust_link, 0, pdata->config.phy_interface);
794 795
795 if (IS_ERR(phydev)) { 796 if (IS_ERR(phydev)) {
796 pr_err("%s: Could not attach to PHY\n", dev->name); 797 pr_err("%s: Could not attach to PHY\n", dev->name);
@@ -1205,14 +1206,14 @@ static int smsc911x_open(struct net_device *dev)
1205 /* Set interrupt deassertion to 100uS */ 1206 /* Set interrupt deassertion to 100uS */
1206 intcfg = ((10 << 24) | INT_CFG_IRQ_EN_); 1207 intcfg = ((10 << 24) | INT_CFG_IRQ_EN_);
1207 1208
1208 if (pdata->irq_polarity) { 1209 if (pdata->config.irq_polarity) {
1209 SMSC_TRACE(IFUP, "irq polarity: active high"); 1210 SMSC_TRACE(IFUP, "irq polarity: active high");
1210 intcfg |= INT_CFG_IRQ_POL_; 1211 intcfg |= INT_CFG_IRQ_POL_;
1211 } else { 1212 } else {
1212 SMSC_TRACE(IFUP, "irq polarity: active low"); 1213 SMSC_TRACE(IFUP, "irq polarity: active low");
1213 } 1214 }
1214 1215
1215 if (pdata->irq_type) { 1216 if (pdata->config.irq_type) {
1216 SMSC_TRACE(IFUP, "irq type: push-pull"); 1217 SMSC_TRACE(IFUP, "irq type: push-pull");
1217 intcfg |= INT_CFG_IRQ_TYPE_; 1218 intcfg |= INT_CFG_IRQ_TYPE_;
1218 } else { 1219 } else {
@@ -1767,9 +1768,7 @@ static int __devinit smsc911x_init(struct net_device *dev)
1767 SMSC_TRACE(PROBE, "IRQ: %d", dev->irq); 1768 SMSC_TRACE(PROBE, "IRQ: %d", dev->irq);
1768 SMSC_TRACE(PROBE, "PHY will be autodetected."); 1769 SMSC_TRACE(PROBE, "PHY will be autodetected.");
1769 1770
1770#if (!SMSC_CAN_USE_32BIT)
1771 spin_lock_init(&pdata->dev_lock); 1771 spin_lock_init(&pdata->dev_lock);
1772#endif
1773 1772
1774 if (pdata->ioaddr == 0) { 1773 if (pdata->ioaddr == 0) {
1775 SMSC_WARNING(PROBE, "pdata->ioaddr: 0x00000000"); 1774 SMSC_WARNING(PROBE, "pdata->ioaddr: 0x00000000");
@@ -1910,6 +1909,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
1910{ 1909{
1911 struct net_device *dev; 1910 struct net_device *dev;
1912 struct smsc911x_data *pdata; 1911 struct smsc911x_data *pdata;
1912 struct smsc911x_platform_config *config = pdev->dev.platform_data;
1913 struct resource *res; 1913 struct resource *res;
1914 unsigned int intcfg = 0; 1914 unsigned int intcfg = 0;
1915 int res_size; 1915 int res_size;
@@ -1918,6 +1918,13 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
1918 1918
1919 pr_info("%s: Driver version %s.\n", SMSC_CHIPNAME, SMSC_DRV_VERSION); 1919 pr_info("%s: Driver version %s.\n", SMSC_CHIPNAME, SMSC_DRV_VERSION);
1920 1920
1921 /* platform data specifies irq & dynamic bus configuration */
1922 if (!pdev->dev.platform_data) {
1923 pr_warning("%s: platform_data not provided\n", SMSC_CHIPNAME);
1924 retval = -ENODEV;
1925 goto out_0;
1926 }
1927
1921 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 1928 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1922 "smsc911x-memory"); 1929 "smsc911x-memory");
1923 if (!res) 1930 if (!res)
@@ -1949,15 +1956,8 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
1949 dev->irq = platform_get_irq(pdev, 0); 1956 dev->irq = platform_get_irq(pdev, 0);
1950 pdata->ioaddr = ioremap_nocache(res->start, res_size); 1957 pdata->ioaddr = ioremap_nocache(res->start, res_size);
1951 1958
1952 /* copy config parameters across if present, otherwise pdata 1959 /* copy config parameters across to pdata */
1953 * defaults to zeros */ 1960 memcpy(&pdata->config, config, sizeof(pdata->config));
1954 if (pdev->dev.platform_data) {
1955 struct smsc911x_platform_config *config =
1956 pdev->dev.platform_data;
1957 pdata->irq_polarity = config->irq_polarity;
1958 pdata->irq_type = config->irq_type;
1959 pdata->phy_interface = config->phy_interface;
1960 }
1961 1961
1962 pdata->dev = dev; 1962 pdata->dev = dev;
1963 pdata->msg_enable = ((1 << debug) - 1); 1963 pdata->msg_enable = ((1 << debug) - 1);
@@ -1974,10 +1974,10 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
1974 goto out_unmap_io_3; 1974 goto out_unmap_io_3;
1975 1975
1976 /* configure irq polarity and type before connecting isr */ 1976 /* configure irq polarity and type before connecting isr */
1977 if (pdata->irq_polarity == SMSC911X_IRQ_POLARITY_ACTIVE_HIGH) 1977 if (pdata->config.irq_polarity == SMSC911X_IRQ_POLARITY_ACTIVE_HIGH)
1978 intcfg |= INT_CFG_IRQ_POL_; 1978 intcfg |= INT_CFG_IRQ_POL_;
1979 1979
1980 if (pdata->irq_type == SMSC911X_IRQ_TYPE_PUSH_PULL) 1980 if (pdata->config.irq_type == SMSC911X_IRQ_TYPE_PUSH_PULL)
1981 intcfg |= INT_CFG_IRQ_TYPE_; 1981 intcfg |= INT_CFG_IRQ_TYPE_;
1982 1982
1983 smsc911x_reg_write(pdata, INT_CFG, intcfg); 1983 smsc911x_reg_write(pdata, INT_CFG, intcfg);
diff --git a/drivers/net/smsc911x.h b/drivers/net/smsc911x.h
index feb36de274ca..f818cf0415f7 100644
--- a/drivers/net/smsc911x.h
+++ b/drivers/net/smsc911x.h
@@ -21,7 +21,6 @@
21#ifndef __SMSC911X_H__ 21#ifndef __SMSC911X_H__
22#define __SMSC911X_H__ 22#define __SMSC911X_H__
23 23
24#define SMSC_CAN_USE_32BIT 1
25#define TX_FIFO_LOW_THRESHOLD ((u32)1600) 24#define TX_FIFO_LOW_THRESHOLD ((u32)1600)
26#define SMSC911X_EEPROM_SIZE ((u32)7) 25#define SMSC911X_EEPROM_SIZE ((u32)7)
27#define USE_DEBUG 0 26#define USE_DEBUG 0