diff options
author | Stephen Hemminger <shemminger@osdl.org> | 2006-12-01 19:36:17 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-12-02 00:24:49 -0500 |
commit | 352c417ddb593de757f0ee1fa490cb5444778c41 (patch) | |
tree | dd1047e7611f09511c3ad1432a3f49b553b0e91e /drivers/net/chelsio/subr.c | |
parent | f1d3d38af75789f1b82969b83b69cab540609789 (diff) |
[PATCH] chelsio: add 1G swcixw aupport
Add support for 1G versions of Chelsio devices.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/chelsio/subr.c')
-rw-r--r-- | drivers/net/chelsio/subr.c | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/drivers/net/chelsio/subr.c b/drivers/net/chelsio/subr.c index d41d15a71e4d..22ed9a383c08 100644 --- a/drivers/net/chelsio/subr.c +++ b/drivers/net/chelsio/subr.c | |||
@@ -185,6 +185,66 @@ static int t1_pci_intr_handler(adapter_t *adapter) | |||
185 | return 0; | 185 | return 0; |
186 | } | 186 | } |
187 | 187 | ||
188 | #ifdef CONFIG_CHELSIO_T1_COUGAR | ||
189 | #include "cspi.h" | ||
190 | #endif | ||
191 | #ifdef CONFIG_CHELSIO_T1_1G | ||
192 | #include "fpga_defs.h" | ||
193 | |||
194 | /* | ||
195 | * PHY interrupt handler for FPGA boards. | ||
196 | */ | ||
197 | static int fpga_phy_intr_handler(adapter_t *adapter) | ||
198 | { | ||
199 | int p; | ||
200 | u32 cause = readl(adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_CAUSE); | ||
201 | |||
202 | for_each_port(adapter, p) | ||
203 | if (cause & (1 << p)) { | ||
204 | struct cphy *phy = adapter->port[p].phy; | ||
205 | int phy_cause = phy->ops->interrupt_handler(phy); | ||
206 | |||
207 | if (phy_cause & cphy_cause_link_change) | ||
208 | t1_link_changed(adapter, p); | ||
209 | } | ||
210 | writel(cause, adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_CAUSE); | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | /* | ||
215 | * Slow path interrupt handler for FPGAs. | ||
216 | */ | ||
217 | static int fpga_slow_intr(adapter_t *adapter) | ||
218 | { | ||
219 | u32 cause = readl(adapter->regs + A_PL_CAUSE); | ||
220 | |||
221 | cause &= ~F_PL_INTR_SGE_DATA; | ||
222 | if (cause & F_PL_INTR_SGE_ERR) | ||
223 | t1_sge_intr_error_handler(adapter->sge); | ||
224 | |||
225 | if (cause & FPGA_PCIX_INTERRUPT_GMAC) | ||
226 | fpga_phy_intr_handler(adapter); | ||
227 | |||
228 | if (cause & FPGA_PCIX_INTERRUPT_TP) { | ||
229 | /* | ||
230 | * FPGA doesn't support MC4 interrupts and it requires | ||
231 | * this odd layer of indirection for MC5. | ||
232 | */ | ||
233 | u32 tp_cause = readl(adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE); | ||
234 | |||
235 | /* Clear TP interrupt */ | ||
236 | writel(tp_cause, adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE); | ||
237 | } | ||
238 | if (cause & FPGA_PCIX_INTERRUPT_PCIX) | ||
239 | t1_pci_intr_handler(adapter); | ||
240 | |||
241 | /* Clear the interrupts just processed. */ | ||
242 | if (cause) | ||
243 | writel(cause, adapter->regs + A_PL_CAUSE); | ||
244 | |||
245 | return cause != 0; | ||
246 | } | ||
247 | #endif | ||
188 | 248 | ||
189 | /* | 249 | /* |
190 | * Wait until Elmer's MI1 interface is ready for new operations. | 250 | * Wait until Elmer's MI1 interface is ready for new operations. |
@@ -221,6 +281,56 @@ static void mi1_mdio_init(adapter_t *adapter, const struct board_info *bi) | |||
221 | t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_CFG, val); | 281 | t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_CFG, val); |
222 | } | 282 | } |
223 | 283 | ||
284 | #if defined(CONFIG_CHELSIO_T1_1G) || defined(CONFIG_CHELSIO_T1_COUGAR) | ||
285 | /* | ||
286 | * Elmer MI1 MDIO read/write operations. | ||
287 | */ | ||
288 | static int mi1_mdio_read(adapter_t *adapter, int phy_addr, int mmd_addr, | ||
289 | int reg_addr, unsigned int *valp) | ||
290 | { | ||
291 | u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr); | ||
292 | |||
293 | if (mmd_addr) | ||
294 | return -EINVAL; | ||
295 | |||
296 | spin_lock(&adapter->tpi_lock); | ||
297 | __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr); | ||
298 | __t1_tpi_write(adapter, | ||
299 | A_ELMER0_PORT0_MI1_OP, MI1_OP_DIRECT_READ); | ||
300 | mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP); | ||
301 | __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp); | ||
302 | spin_unlock(&adapter->tpi_lock); | ||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static int mi1_mdio_write(adapter_t *adapter, int phy_addr, int mmd_addr, | ||
307 | int reg_addr, unsigned int val) | ||
308 | { | ||
309 | u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr); | ||
310 | |||
311 | if (mmd_addr) | ||
312 | return -EINVAL; | ||
313 | |||
314 | spin_lock(&adapter->tpi_lock); | ||
315 | __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr); | ||
316 | __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val); | ||
317 | __t1_tpi_write(adapter, | ||
318 | A_ELMER0_PORT0_MI1_OP, MI1_OP_DIRECT_WRITE); | ||
319 | mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP); | ||
320 | spin_unlock(&adapter->tpi_lock); | ||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | #if defined(CONFIG_CHELSIO_T1_1G) || defined(CONFIG_CHELSIO_T1_COUGAR) | ||
325 | static struct mdio_ops mi1_mdio_ops = { | ||
326 | mi1_mdio_init, | ||
327 | mi1_mdio_read, | ||
328 | mi1_mdio_write | ||
329 | }; | ||
330 | #endif | ||
331 | |||
332 | #endif | ||
333 | |||
224 | static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr, | 334 | static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr, |
225 | int reg_addr, unsigned int *valp) | 335 | int reg_addr, unsigned int *valp) |
226 | { | 336 | { |
@@ -330,6 +440,17 @@ static struct board_info t1_board[] = { | |||
330 | &t1_my3126_ops, &mi1_mdio_ext_ops, | 440 | &t1_my3126_ops, &mi1_mdio_ext_ops, |
331 | "Chelsio T210 1x10GBase-CX4 TOE" }, | 441 | "Chelsio T210 1x10GBase-CX4 TOE" }, |
332 | 442 | ||
443 | #ifdef CONFIG_CHELSIO_T1_1G | ||
444 | { CHBT_BOARD_CHN204, 4/*ports#*/, | ||
445 | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | | ||
446 | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | | ||
447 | SUPPORTED_PAUSE | SUPPORTED_TP /*caps*/, CHBT_TERM_T2, CHBT_MAC_VSC7321, CHBT_PHY_88E1111, | ||
448 | 100000000/*clk-core*/, 0/*clk-mc3*/, 0/*clk-mc4*/, | ||
449 | 4/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 0/*mdien*/, | ||
450 | 0/*mdiinv*/, 1/*mdc*/, 4/*phybaseaddr*/, &t1_vsc7326_ops, | ||
451 | &t1_mv88e1xxx_ops, &mi1_mdio_ops, | ||
452 | "Chelsio N204 4x100/1000BaseT NIC" }, | ||
453 | #endif | ||
333 | 454 | ||
334 | }; | 455 | }; |
335 | 456 | ||
@@ -483,6 +604,48 @@ int t1_elmer0_ext_intr_handler(adapter_t *adapter) | |||
483 | t1_tpi_read(adapter, A_ELMER0_INT_CAUSE, &cause); | 604 | t1_tpi_read(adapter, A_ELMER0_INT_CAUSE, &cause); |
484 | 605 | ||
485 | switch (board_info(adapter)->board) { | 606 | switch (board_info(adapter)->board) { |
607 | #ifdef CONFIG_CHELSIO_T1_1G | ||
608 | case CHBT_BOARD_CHT204: | ||
609 | case CHBT_BOARD_CHT204E: | ||
610 | case CHBT_BOARD_CHN204: | ||
611 | case CHBT_BOARD_CHT204V: { | ||
612 | int i, port_bit; | ||
613 | for_each_port(adapter, i) { | ||
614 | port_bit = i + 1; | ||
615 | if (!(cause & (1 << port_bit))) continue; | ||
616 | |||
617 | phy = adapter->port[i].phy; | ||
618 | phy_cause = phy->ops->interrupt_handler(phy); | ||
619 | if (phy_cause & cphy_cause_link_change) | ||
620 | t1_link_changed(adapter, i); | ||
621 | } | ||
622 | break; | ||
623 | } | ||
624 | case CHBT_BOARD_CHT101: | ||
625 | if (cause & ELMER0_GP_BIT1) { /* Marvell 88E1111 interrupt */ | ||
626 | phy = adapter->port[0].phy; | ||
627 | phy_cause = phy->ops->interrupt_handler(phy); | ||
628 | if (phy_cause & cphy_cause_link_change) | ||
629 | t1_link_changed(adapter, 0); | ||
630 | } | ||
631 | break; | ||
632 | case CHBT_BOARD_7500: { | ||
633 | int p; | ||
634 | /* | ||
635 | * Elmer0's interrupt cause isn't useful here because there is | ||
636 | * only one bit that can be set for all 4 ports. This means | ||
637 | * we are forced to check every PHY's interrupt status | ||
638 | * register to see who initiated the interrupt. | ||
639 | */ | ||
640 | for_each_port(adapter, p) { | ||
641 | phy = adapter->port[p].phy; | ||
642 | phy_cause = phy->ops->interrupt_handler(phy); | ||
643 | if (phy_cause & cphy_cause_link_change) | ||
644 | t1_link_changed(adapter, p); | ||
645 | } | ||
646 | break; | ||
647 | } | ||
648 | #endif | ||
486 | case CHBT_BOARD_CHT210: | 649 | case CHBT_BOARD_CHT210: |
487 | case CHBT_BOARD_N210: | 650 | case CHBT_BOARD_N210: |
488 | case CHBT_BOARD_N110: | 651 | case CHBT_BOARD_N110: |
@@ -511,6 +674,30 @@ int t1_elmer0_ext_intr_handler(adapter_t *adapter) | |||
511 | mod_detect ? "removed" : "inserted"); | 674 | mod_detect ? "removed" : "inserted"); |
512 | } | 675 | } |
513 | break; | 676 | break; |
677 | #ifdef CONFIG_CHELSIO_T1_COUGAR | ||
678 | case CHBT_BOARD_COUGAR: | ||
679 | if (adapter->params.nports == 1) { | ||
680 | if (cause & ELMER0_GP_BIT1) { /* Vitesse MAC */ | ||
681 | struct cmac *mac = adapter->port[0].mac; | ||
682 | mac->ops->interrupt_handler(mac); | ||
683 | } | ||
684 | if (cause & ELMER0_GP_BIT5) { /* XPAK MOD_DETECT */ | ||
685 | } | ||
686 | } else { | ||
687 | int i, port_bit; | ||
688 | |||
689 | for_each_port(adapter, i) { | ||
690 | port_bit = i ? i + 1 : 0; | ||
691 | if (!(cause & (1 << port_bit))) continue; | ||
692 | |||
693 | phy = adapter->port[i].phy; | ||
694 | phy_cause = phy->ops->interrupt_handler(phy); | ||
695 | if (phy_cause & cphy_cause_link_change) | ||
696 | t1_link_changed(adapter, i); | ||
697 | } | ||
698 | } | ||
699 | break; | ||
700 | #endif | ||
514 | } | 701 | } |
515 | t1_tpi_write(adapter, A_ELMER0_INT_CAUSE, cause); | 702 | t1_tpi_write(adapter, A_ELMER0_INT_CAUSE, cause); |
516 | return 0; | 703 | return 0; |
@@ -633,6 +820,10 @@ static int asic_slow_intr(adapter_t *adapter) | |||
633 | 820 | ||
634 | int t1_slow_intr_handler(adapter_t *adapter) | 821 | int t1_slow_intr_handler(adapter_t *adapter) |
635 | { | 822 | { |
823 | #ifdef CONFIG_CHELSIO_T1_1G | ||
824 | if (!t1_is_asic(adapter)) | ||
825 | return fpga_slow_intr(adapter); | ||
826 | #endif | ||
636 | return asic_slow_intr(adapter); | 827 | return asic_slow_intr(adapter); |
637 | } | 828 | } |
638 | 829 | ||
@@ -698,6 +889,21 @@ static int board_init(adapter_t *adapter, const struct board_info *bi) | |||
698 | */ | 889 | */ |
699 | power_sequence_xpak(adapter); | 890 | power_sequence_xpak(adapter); |
700 | break; | 891 | break; |
892 | #ifdef CONFIG_CHELSIO_T1_1G | ||
893 | case CHBT_BOARD_CHT204E: | ||
894 | /* add config space write here */ | ||
895 | case CHBT_BOARD_CHT204: | ||
896 | case CHBT_BOARD_CHT204V: | ||
897 | case CHBT_BOARD_CHN204: | ||
898 | t1_tpi_par(adapter, 0xf); | ||
899 | t1_tpi_write(adapter, A_ELMER0_GPO, 0x804); | ||
900 | break; | ||
901 | case CHBT_BOARD_CHT101: | ||
902 | case CHBT_BOARD_7500: | ||
903 | t1_tpi_par(adapter, 0xf); | ||
904 | t1_tpi_write(adapter, A_ELMER0_GPO, 0x1804); | ||
905 | break; | ||
906 | #endif | ||
701 | } | 907 | } |
702 | return 0; | 908 | return 0; |
703 | } | 909 | } |
@@ -719,6 +925,10 @@ int t1_init_hw_modules(adapter_t *adapter) | |||
719 | adapter->regs + A_MC5_CONFIG); | 925 | adapter->regs + A_MC5_CONFIG); |
720 | } | 926 | } |
721 | 927 | ||
928 | #ifdef CONFIG_CHELSIO_T1_COUGAR | ||
929 | if (adapter->cspi && t1_cspi_init(adapter->cspi)) | ||
930 | goto out_err; | ||
931 | #endif | ||
722 | if (adapter->espi && t1_espi_init(adapter->espi, bi->chip_mac, | 932 | if (adapter->espi && t1_espi_init(adapter->espi, bi->chip_mac, |
723 | bi->espi_nports)) | 933 | bi->espi_nports)) |
724 | goto out_err; | 934 | goto out_err; |
@@ -772,6 +982,10 @@ void t1_free_sw_modules(adapter_t *adapter) | |||
772 | t1_tp_destroy(adapter->tp); | 982 | t1_tp_destroy(adapter->tp); |
773 | if (adapter->espi) | 983 | if (adapter->espi) |
774 | t1_espi_destroy(adapter->espi); | 984 | t1_espi_destroy(adapter->espi); |
985 | #ifdef CONFIG_CHELSIO_T1_COUGAR | ||
986 | if (adapter->cspi) | ||
987 | t1_cspi_destroy(adapter->cspi); | ||
988 | #endif | ||
775 | } | 989 | } |
776 | 990 | ||
777 | static void __devinit init_link_config(struct link_config *lc, | 991 | static void __devinit init_link_config(struct link_config *lc, |
@@ -791,6 +1005,13 @@ static void __devinit init_link_config(struct link_config *lc, | |||
791 | } | 1005 | } |
792 | } | 1006 | } |
793 | 1007 | ||
1008 | #ifdef CONFIG_CHELSIO_T1_COUGAR | ||
1009 | if (bi->clock_cspi && !(adapter->cspi = t1_cspi_create(adapter))) { | ||
1010 | CH_ERR("%s: CSPI initialization failed\n", | ||
1011 | adapter->name); | ||
1012 | goto error; | ||
1013 | } | ||
1014 | #endif | ||
794 | 1015 | ||
795 | /* | 1016 | /* |
796 | * Allocate and initialize the data structures that hold the SW state of | 1017 | * Allocate and initialize the data structures that hold the SW state of |