18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2007, 2011 Wolfgang Grandegger <wg@grandegger.com> 48c2ecf20Sopenharmony_ci * Copyright (C) 2012 Stephane Grosjean <s.grosjean@peak-system.com> 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Derived from the PCAN project file driver/src/pcan_pci.c: 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Copyright (C) 2001-2006 PEAK System-Technik GmbH 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/kernel.h> 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 148c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 158c2ecf20Sopenharmony_ci#include <linux/delay.h> 168c2ecf20Sopenharmony_ci#include <linux/pci.h> 178c2ecf20Sopenharmony_ci#include <linux/io.h> 188c2ecf20Sopenharmony_ci#include <linux/i2c.h> 198c2ecf20Sopenharmony_ci#include <linux/i2c-algo-bit.h> 208c2ecf20Sopenharmony_ci#include <linux/can.h> 218c2ecf20Sopenharmony_ci#include <linux/can/dev.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include "sja1000.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ciMODULE_AUTHOR("Stephane Grosjean <s.grosjean@peak-system.com>"); 268c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Socket-CAN driver for PEAK PCAN PCI family cards"); 278c2ecf20Sopenharmony_ciMODULE_SUPPORTED_DEVICE("PEAK PCAN PCI/PCIe/PCIeC miniPCI CAN cards"); 288c2ecf20Sopenharmony_ciMODULE_SUPPORTED_DEVICE("PEAK PCAN miniPCIe/cPCI PC/104+ PCI/104e CAN Cards"); 298c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define DRV_NAME "peak_pci" 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistruct peak_pciec_card; 348c2ecf20Sopenharmony_cistruct peak_pci_chan { 358c2ecf20Sopenharmony_ci void __iomem *cfg_base; /* Common for all channels */ 368c2ecf20Sopenharmony_ci struct net_device *prev_dev; /* Chain of network devices */ 378c2ecf20Sopenharmony_ci u16 icr_mask; /* Interrupt mask for fast ack */ 388c2ecf20Sopenharmony_ci struct peak_pciec_card *pciec_card; /* only for PCIeC LEDs */ 398c2ecf20Sopenharmony_ci}; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#define PEAK_PCI_CAN_CLOCK (16000000 / 2) 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#define PEAK_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK) 448c2ecf20Sopenharmony_ci#define PEAK_PCI_OCR OCR_TX0_PUSHPULL 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/* 478c2ecf20Sopenharmony_ci * Important PITA registers 488c2ecf20Sopenharmony_ci */ 498c2ecf20Sopenharmony_ci#define PITA_ICR 0x00 /* Interrupt control register */ 508c2ecf20Sopenharmony_ci#define PITA_GPIOICR 0x18 /* GPIO interface control register */ 518c2ecf20Sopenharmony_ci#define PITA_MISC 0x1C /* Miscellaneous register */ 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#define PEAK_PCI_CFG_SIZE 0x1000 /* Size of the config PCI bar */ 548c2ecf20Sopenharmony_ci#define PEAK_PCI_CHAN_SIZE 0x0400 /* Size used by the channel */ 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci#define PEAK_PCI_VENDOR_ID 0x001C /* The PCI device and vendor IDs */ 578c2ecf20Sopenharmony_ci#define PEAK_PCI_DEVICE_ID 0x0001 /* for PCI/PCIe slot cards */ 588c2ecf20Sopenharmony_ci#define PEAK_PCIEC_DEVICE_ID 0x0002 /* for ExpressCard slot cards */ 598c2ecf20Sopenharmony_ci#define PEAK_PCIE_DEVICE_ID 0x0003 /* for nextgen PCIe slot cards */ 608c2ecf20Sopenharmony_ci#define PEAK_CPCI_DEVICE_ID 0x0004 /* for nextgen cPCI slot cards */ 618c2ecf20Sopenharmony_ci#define PEAK_MPCI_DEVICE_ID 0x0005 /* for nextgen miniPCI slot cards */ 628c2ecf20Sopenharmony_ci#define PEAK_PC_104P_DEVICE_ID 0x0006 /* PCAN-PC/104+ cards */ 638c2ecf20Sopenharmony_ci#define PEAK_PCI_104E_DEVICE_ID 0x0007 /* PCAN-PCI/104 Express cards */ 648c2ecf20Sopenharmony_ci#define PEAK_MPCIE_DEVICE_ID 0x0008 /* The miniPCIe slot cards */ 658c2ecf20Sopenharmony_ci#define PEAK_PCIE_OEM_ID 0x0009 /* PCAN-PCI Express OEM */ 668c2ecf20Sopenharmony_ci#define PEAK_PCIEC34_DEVICE_ID 0x000A /* PCAN-PCI Express 34 (one channel) */ 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci#define PEAK_PCI_CHAN_MAX 4 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic const u16 peak_pci_icr_masks[PEAK_PCI_CHAN_MAX] = { 718c2ecf20Sopenharmony_ci 0x02, 0x01, 0x40, 0x80 728c2ecf20Sopenharmony_ci}; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic const struct pci_device_id peak_pci_tbl[] = { 758c2ecf20Sopenharmony_ci {PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, 768c2ecf20Sopenharmony_ci {PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, 778c2ecf20Sopenharmony_ci {PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, 788c2ecf20Sopenharmony_ci {PEAK_PCI_VENDOR_ID, PEAK_MPCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, 798c2ecf20Sopenharmony_ci {PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, 808c2ecf20Sopenharmony_ci {PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, 818c2ecf20Sopenharmony_ci {PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, 828c2ecf20Sopenharmony_ci {PEAK_PCI_VENDOR_ID, PEAK_PCIE_OEM_ID, PCI_ANY_ID, PCI_ANY_ID,}, 838c2ecf20Sopenharmony_ci#ifdef CONFIG_CAN_PEAK_PCIEC 848c2ecf20Sopenharmony_ci {PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, 858c2ecf20Sopenharmony_ci {PEAK_PCI_VENDOR_ID, PEAK_PCIEC34_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, 868c2ecf20Sopenharmony_ci#endif 878c2ecf20Sopenharmony_ci {0,} 888c2ecf20Sopenharmony_ci}; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, peak_pci_tbl); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci#ifdef CONFIG_CAN_PEAK_PCIEC 938c2ecf20Sopenharmony_ci/* 948c2ecf20Sopenharmony_ci * PCAN-ExpressCard needs I2C bit-banging configuration option. 958c2ecf20Sopenharmony_ci */ 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci/* GPIOICR byte access offsets */ 988c2ecf20Sopenharmony_ci#define PITA_GPOUT 0x18 /* GPx output value */ 998c2ecf20Sopenharmony_ci#define PITA_GPIN 0x19 /* GPx input value */ 1008c2ecf20Sopenharmony_ci#define PITA_GPOEN 0x1A /* configure GPx as output pin */ 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci/* I2C GP bits */ 1038c2ecf20Sopenharmony_ci#define PITA_GPIN_SCL 0x01 /* Serial Clock Line */ 1048c2ecf20Sopenharmony_ci#define PITA_GPIN_SDA 0x04 /* Serial DAta line */ 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci#define PCA9553_1_SLAVEADDR (0xC4 >> 1) 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci/* PCA9553 LS0 fields values */ 1098c2ecf20Sopenharmony_cienum { 1108c2ecf20Sopenharmony_ci PCA9553_LOW, 1118c2ecf20Sopenharmony_ci PCA9553_HIGHZ, 1128c2ecf20Sopenharmony_ci PCA9553_PWM0, 1138c2ecf20Sopenharmony_ci PCA9553_PWM1 1148c2ecf20Sopenharmony_ci}; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci/* LEDs control */ 1178c2ecf20Sopenharmony_ci#define PCA9553_ON PCA9553_LOW 1188c2ecf20Sopenharmony_ci#define PCA9553_OFF PCA9553_HIGHZ 1198c2ecf20Sopenharmony_ci#define PCA9553_SLOW PCA9553_PWM0 1208c2ecf20Sopenharmony_ci#define PCA9553_FAST PCA9553_PWM1 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci#define PCA9553_LED(c) (1 << (c)) 1238c2ecf20Sopenharmony_ci#define PCA9553_LED_STATE(s, c) ((s) << ((c) << 1)) 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci#define PCA9553_LED_ON(c) PCA9553_LED_STATE(PCA9553_ON, c) 1268c2ecf20Sopenharmony_ci#define PCA9553_LED_OFF(c) PCA9553_LED_STATE(PCA9553_OFF, c) 1278c2ecf20Sopenharmony_ci#define PCA9553_LED_SLOW(c) PCA9553_LED_STATE(PCA9553_SLOW, c) 1288c2ecf20Sopenharmony_ci#define PCA9553_LED_FAST(c) PCA9553_LED_STATE(PCA9553_FAST, c) 1298c2ecf20Sopenharmony_ci#define PCA9553_LED_MASK(c) PCA9553_LED_STATE(0x03, c) 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci#define PCA9553_LED_OFF_ALL (PCA9553_LED_OFF(0) | PCA9553_LED_OFF(1)) 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci#define PCA9553_LS0_INIT 0x40 /* initial value (!= from 0x00) */ 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistruct peak_pciec_chan { 1368c2ecf20Sopenharmony_ci struct net_device *netdev; 1378c2ecf20Sopenharmony_ci unsigned long prev_rx_bytes; 1388c2ecf20Sopenharmony_ci unsigned long prev_tx_bytes; 1398c2ecf20Sopenharmony_ci}; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_cistruct peak_pciec_card { 1428c2ecf20Sopenharmony_ci void __iomem *cfg_base; /* Common for all channels */ 1438c2ecf20Sopenharmony_ci void __iomem *reg_base; /* first channel base address */ 1448c2ecf20Sopenharmony_ci u8 led_cache; /* leds state cache */ 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci /* PCIExpressCard i2c data */ 1478c2ecf20Sopenharmony_ci struct i2c_algo_bit_data i2c_bit; 1488c2ecf20Sopenharmony_ci struct i2c_adapter led_chip; 1498c2ecf20Sopenharmony_ci struct delayed_work led_work; /* led delayed work */ 1508c2ecf20Sopenharmony_ci int chan_count; 1518c2ecf20Sopenharmony_ci struct peak_pciec_chan channel[PEAK_PCI_CHAN_MAX]; 1528c2ecf20Sopenharmony_ci}; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci/* "normal" pci register write callback is overloaded for leds control */ 1558c2ecf20Sopenharmony_cistatic void peak_pci_write_reg(const struct sja1000_priv *priv, 1568c2ecf20Sopenharmony_ci int port, u8 val); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistatic inline void pita_set_scl_highz(struct peak_pciec_card *card) 1598c2ecf20Sopenharmony_ci{ 1608c2ecf20Sopenharmony_ci u8 gp_outen = readb(card->cfg_base + PITA_GPOEN) & ~PITA_GPIN_SCL; 1618c2ecf20Sopenharmony_ci writeb(gp_outen, card->cfg_base + PITA_GPOEN); 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic inline void pita_set_sda_highz(struct peak_pciec_card *card) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci u8 gp_outen = readb(card->cfg_base + PITA_GPOEN) & ~PITA_GPIN_SDA; 1678c2ecf20Sopenharmony_ci writeb(gp_outen, card->cfg_base + PITA_GPOEN); 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistatic void peak_pciec_init_pita_gpio(struct peak_pciec_card *card) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci /* raise SCL & SDA GPIOs to high-Z */ 1738c2ecf20Sopenharmony_ci pita_set_scl_highz(card); 1748c2ecf20Sopenharmony_ci pita_set_sda_highz(card); 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cistatic void pita_setsda(void *data, int state) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci struct peak_pciec_card *card = (struct peak_pciec_card *)data; 1808c2ecf20Sopenharmony_ci u8 gp_out, gp_outen; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci /* set output sda always to 0 */ 1838c2ecf20Sopenharmony_ci gp_out = readb(card->cfg_base + PITA_GPOUT) & ~PITA_GPIN_SDA; 1848c2ecf20Sopenharmony_ci writeb(gp_out, card->cfg_base + PITA_GPOUT); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci /* control output sda with GPOEN */ 1878c2ecf20Sopenharmony_ci gp_outen = readb(card->cfg_base + PITA_GPOEN); 1888c2ecf20Sopenharmony_ci if (state) 1898c2ecf20Sopenharmony_ci gp_outen &= ~PITA_GPIN_SDA; 1908c2ecf20Sopenharmony_ci else 1918c2ecf20Sopenharmony_ci gp_outen |= PITA_GPIN_SDA; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci writeb(gp_outen, card->cfg_base + PITA_GPOEN); 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_cistatic void pita_setscl(void *data, int state) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci struct peak_pciec_card *card = (struct peak_pciec_card *)data; 1998c2ecf20Sopenharmony_ci u8 gp_out, gp_outen; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci /* set output scl always to 0 */ 2028c2ecf20Sopenharmony_ci gp_out = readb(card->cfg_base + PITA_GPOUT) & ~PITA_GPIN_SCL; 2038c2ecf20Sopenharmony_ci writeb(gp_out, card->cfg_base + PITA_GPOUT); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci /* control output scl with GPOEN */ 2068c2ecf20Sopenharmony_ci gp_outen = readb(card->cfg_base + PITA_GPOEN); 2078c2ecf20Sopenharmony_ci if (state) 2088c2ecf20Sopenharmony_ci gp_outen &= ~PITA_GPIN_SCL; 2098c2ecf20Sopenharmony_ci else 2108c2ecf20Sopenharmony_ci gp_outen |= PITA_GPIN_SCL; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci writeb(gp_outen, card->cfg_base + PITA_GPOEN); 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic int pita_getsda(void *data) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci struct peak_pciec_card *card = (struct peak_pciec_card *)data; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci /* set tristate */ 2208c2ecf20Sopenharmony_ci pita_set_sda_highz(card); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci return (readb(card->cfg_base + PITA_GPIN) & PITA_GPIN_SDA) ? 1 : 0; 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistatic int pita_getscl(void *data) 2268c2ecf20Sopenharmony_ci{ 2278c2ecf20Sopenharmony_ci struct peak_pciec_card *card = (struct peak_pciec_card *)data; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci /* set tristate */ 2308c2ecf20Sopenharmony_ci pita_set_scl_highz(card); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci return (readb(card->cfg_base + PITA_GPIN) & PITA_GPIN_SCL) ? 1 : 0; 2338c2ecf20Sopenharmony_ci} 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci/* 2368c2ecf20Sopenharmony_ci * write commands to the LED chip though the I2C-bus of the PCAN-PCIeC 2378c2ecf20Sopenharmony_ci */ 2388c2ecf20Sopenharmony_cistatic int peak_pciec_write_pca9553(struct peak_pciec_card *card, 2398c2ecf20Sopenharmony_ci u8 offset, u8 data) 2408c2ecf20Sopenharmony_ci{ 2418c2ecf20Sopenharmony_ci u8 buffer[2] = { 2428c2ecf20Sopenharmony_ci offset, 2438c2ecf20Sopenharmony_ci data 2448c2ecf20Sopenharmony_ci }; 2458c2ecf20Sopenharmony_ci struct i2c_msg msg = { 2468c2ecf20Sopenharmony_ci .addr = PCA9553_1_SLAVEADDR, 2478c2ecf20Sopenharmony_ci .len = 2, 2488c2ecf20Sopenharmony_ci .buf = buffer, 2498c2ecf20Sopenharmony_ci }; 2508c2ecf20Sopenharmony_ci int ret; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci /* cache led mask */ 2538c2ecf20Sopenharmony_ci if ((offset == 5) && (data == card->led_cache)) 2548c2ecf20Sopenharmony_ci return 0; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci ret = i2c_transfer(&card->led_chip, &msg, 1); 2578c2ecf20Sopenharmony_ci if (ret < 0) 2588c2ecf20Sopenharmony_ci return ret; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci if (offset == 5) 2618c2ecf20Sopenharmony_ci card->led_cache = data; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci return 0; 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci/* 2678c2ecf20Sopenharmony_ci * delayed work callback used to control the LEDs 2688c2ecf20Sopenharmony_ci */ 2698c2ecf20Sopenharmony_cistatic void peak_pciec_led_work(struct work_struct *work) 2708c2ecf20Sopenharmony_ci{ 2718c2ecf20Sopenharmony_ci struct peak_pciec_card *card = 2728c2ecf20Sopenharmony_ci container_of(work, struct peak_pciec_card, led_work.work); 2738c2ecf20Sopenharmony_ci struct net_device *netdev; 2748c2ecf20Sopenharmony_ci u8 new_led = card->led_cache; 2758c2ecf20Sopenharmony_ci int i, up_count = 0; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci /* first check what is to do */ 2788c2ecf20Sopenharmony_ci for (i = 0; i < card->chan_count; i++) { 2798c2ecf20Sopenharmony_ci /* default is: not configured */ 2808c2ecf20Sopenharmony_ci new_led &= ~PCA9553_LED_MASK(i); 2818c2ecf20Sopenharmony_ci new_led |= PCA9553_LED_ON(i); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci netdev = card->channel[i].netdev; 2848c2ecf20Sopenharmony_ci if (!netdev || !(netdev->flags & IFF_UP)) 2858c2ecf20Sopenharmony_ci continue; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci up_count++; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci /* no activity (but configured) */ 2908c2ecf20Sopenharmony_ci new_led &= ~PCA9553_LED_MASK(i); 2918c2ecf20Sopenharmony_ci new_led |= PCA9553_LED_SLOW(i); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci /* if bytes counters changed, set fast blinking led */ 2948c2ecf20Sopenharmony_ci if (netdev->stats.rx_bytes != card->channel[i].prev_rx_bytes) { 2958c2ecf20Sopenharmony_ci card->channel[i].prev_rx_bytes = netdev->stats.rx_bytes; 2968c2ecf20Sopenharmony_ci new_led &= ~PCA9553_LED_MASK(i); 2978c2ecf20Sopenharmony_ci new_led |= PCA9553_LED_FAST(i); 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci if (netdev->stats.tx_bytes != card->channel[i].prev_tx_bytes) { 3008c2ecf20Sopenharmony_ci card->channel[i].prev_tx_bytes = netdev->stats.tx_bytes; 3018c2ecf20Sopenharmony_ci new_led &= ~PCA9553_LED_MASK(i); 3028c2ecf20Sopenharmony_ci new_led |= PCA9553_LED_FAST(i); 3038c2ecf20Sopenharmony_ci } 3048c2ecf20Sopenharmony_ci } 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci /* check if LS0 settings changed, only update i2c if so */ 3078c2ecf20Sopenharmony_ci peak_pciec_write_pca9553(card, 5, new_led); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci /* restart timer (except if no more configured channels) */ 3108c2ecf20Sopenharmony_ci if (up_count) 3118c2ecf20Sopenharmony_ci schedule_delayed_work(&card->led_work, HZ); 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci/* 3158c2ecf20Sopenharmony_ci * set LEDs blinking state 3168c2ecf20Sopenharmony_ci */ 3178c2ecf20Sopenharmony_cistatic void peak_pciec_set_leds(struct peak_pciec_card *card, u8 led_mask, u8 s) 3188c2ecf20Sopenharmony_ci{ 3198c2ecf20Sopenharmony_ci u8 new_led = card->led_cache; 3208c2ecf20Sopenharmony_ci int i; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci /* first check what is to do */ 3238c2ecf20Sopenharmony_ci for (i = 0; i < card->chan_count; i++) 3248c2ecf20Sopenharmony_ci if (led_mask & PCA9553_LED(i)) { 3258c2ecf20Sopenharmony_ci new_led &= ~PCA9553_LED_MASK(i); 3268c2ecf20Sopenharmony_ci new_led |= PCA9553_LED_STATE(s, i); 3278c2ecf20Sopenharmony_ci } 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci /* check if LS0 settings changed, only update i2c if so */ 3308c2ecf20Sopenharmony_ci peak_pciec_write_pca9553(card, 5, new_led); 3318c2ecf20Sopenharmony_ci} 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci/* 3348c2ecf20Sopenharmony_ci * start one second delayed work to control LEDs 3358c2ecf20Sopenharmony_ci */ 3368c2ecf20Sopenharmony_cistatic void peak_pciec_start_led_work(struct peak_pciec_card *card) 3378c2ecf20Sopenharmony_ci{ 3388c2ecf20Sopenharmony_ci schedule_delayed_work(&card->led_work, HZ); 3398c2ecf20Sopenharmony_ci} 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci/* 3428c2ecf20Sopenharmony_ci * stop LEDs delayed work 3438c2ecf20Sopenharmony_ci */ 3448c2ecf20Sopenharmony_cistatic void peak_pciec_stop_led_work(struct peak_pciec_card *card) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&card->led_work); 3478c2ecf20Sopenharmony_ci} 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci/* 3508c2ecf20Sopenharmony_ci * initialize the PCA9553 4-bit I2C-bus LED chip 3518c2ecf20Sopenharmony_ci */ 3528c2ecf20Sopenharmony_cistatic int peak_pciec_init_leds(struct peak_pciec_card *card) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci int err; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci /* prescaler for frequency 0: "SLOW" = 1 Hz = "44" */ 3578c2ecf20Sopenharmony_ci err = peak_pciec_write_pca9553(card, 1, 44 / 1); 3588c2ecf20Sopenharmony_ci if (err) 3598c2ecf20Sopenharmony_ci return err; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci /* duty cycle 0: 50% */ 3628c2ecf20Sopenharmony_ci err = peak_pciec_write_pca9553(card, 2, 0x80); 3638c2ecf20Sopenharmony_ci if (err) 3648c2ecf20Sopenharmony_ci return err; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci /* prescaler for frequency 1: "FAST" = 5 Hz */ 3678c2ecf20Sopenharmony_ci err = peak_pciec_write_pca9553(card, 3, 44 / 5); 3688c2ecf20Sopenharmony_ci if (err) 3698c2ecf20Sopenharmony_ci return err; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci /* duty cycle 1: 50% */ 3728c2ecf20Sopenharmony_ci err = peak_pciec_write_pca9553(card, 4, 0x80); 3738c2ecf20Sopenharmony_ci if (err) 3748c2ecf20Sopenharmony_ci return err; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci /* switch LEDs to initial state */ 3778c2ecf20Sopenharmony_ci return peak_pciec_write_pca9553(card, 5, PCA9553_LS0_INIT); 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci/* 3818c2ecf20Sopenharmony_ci * restore LEDs state to off peak_pciec_leds_exit 3828c2ecf20Sopenharmony_ci */ 3838c2ecf20Sopenharmony_cistatic void peak_pciec_leds_exit(struct peak_pciec_card *card) 3848c2ecf20Sopenharmony_ci{ 3858c2ecf20Sopenharmony_ci /* switch LEDs to off */ 3868c2ecf20Sopenharmony_ci peak_pciec_write_pca9553(card, 5, PCA9553_LED_OFF_ALL); 3878c2ecf20Sopenharmony_ci} 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci/* 3908c2ecf20Sopenharmony_ci * normal write sja1000 register method overloaded to catch when controller 3918c2ecf20Sopenharmony_ci * is started or stopped, to control leds 3928c2ecf20Sopenharmony_ci */ 3938c2ecf20Sopenharmony_cistatic void peak_pciec_write_reg(const struct sja1000_priv *priv, 3948c2ecf20Sopenharmony_ci int port, u8 val) 3958c2ecf20Sopenharmony_ci{ 3968c2ecf20Sopenharmony_ci struct peak_pci_chan *chan = priv->priv; 3978c2ecf20Sopenharmony_ci struct peak_pciec_card *card = chan->pciec_card; 3988c2ecf20Sopenharmony_ci int c = (priv->reg_base - card->reg_base) / PEAK_PCI_CHAN_SIZE; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci /* sja1000 register changes control the leds state */ 4018c2ecf20Sopenharmony_ci if (port == SJA1000_MOD) 4028c2ecf20Sopenharmony_ci switch (val) { 4038c2ecf20Sopenharmony_ci case MOD_RM: 4048c2ecf20Sopenharmony_ci /* Reset Mode: set led on */ 4058c2ecf20Sopenharmony_ci peak_pciec_set_leds(card, PCA9553_LED(c), PCA9553_ON); 4068c2ecf20Sopenharmony_ci break; 4078c2ecf20Sopenharmony_ci case 0x00: 4088c2ecf20Sopenharmony_ci /* Normal Mode: led slow blinking and start led timer */ 4098c2ecf20Sopenharmony_ci peak_pciec_set_leds(card, PCA9553_LED(c), PCA9553_SLOW); 4108c2ecf20Sopenharmony_ci peak_pciec_start_led_work(card); 4118c2ecf20Sopenharmony_ci break; 4128c2ecf20Sopenharmony_ci default: 4138c2ecf20Sopenharmony_ci break; 4148c2ecf20Sopenharmony_ci } 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci /* call base function */ 4178c2ecf20Sopenharmony_ci peak_pci_write_reg(priv, port, val); 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic const struct i2c_algo_bit_data peak_pciec_i2c_bit_ops = { 4218c2ecf20Sopenharmony_ci .setsda = pita_setsda, 4228c2ecf20Sopenharmony_ci .setscl = pita_setscl, 4238c2ecf20Sopenharmony_ci .getsda = pita_getsda, 4248c2ecf20Sopenharmony_ci .getscl = pita_getscl, 4258c2ecf20Sopenharmony_ci .udelay = 10, 4268c2ecf20Sopenharmony_ci .timeout = HZ, 4278c2ecf20Sopenharmony_ci}; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_cistatic int peak_pciec_probe(struct pci_dev *pdev, struct net_device *dev) 4308c2ecf20Sopenharmony_ci{ 4318c2ecf20Sopenharmony_ci struct sja1000_priv *priv = netdev_priv(dev); 4328c2ecf20Sopenharmony_ci struct peak_pci_chan *chan = priv->priv; 4338c2ecf20Sopenharmony_ci struct peak_pciec_card *card; 4348c2ecf20Sopenharmony_ci int err; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci /* copy i2c object address from 1st channel */ 4378c2ecf20Sopenharmony_ci if (chan->prev_dev) { 4388c2ecf20Sopenharmony_ci struct sja1000_priv *prev_priv = netdev_priv(chan->prev_dev); 4398c2ecf20Sopenharmony_ci struct peak_pci_chan *prev_chan = prev_priv->priv; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci card = prev_chan->pciec_card; 4428c2ecf20Sopenharmony_ci if (!card) 4438c2ecf20Sopenharmony_ci return -ENODEV; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci /* channel is the first one: do the init part */ 4468c2ecf20Sopenharmony_ci } else { 4478c2ecf20Sopenharmony_ci /* create the bit banging I2C adapter structure */ 4488c2ecf20Sopenharmony_ci card = kzalloc(sizeof(struct peak_pciec_card), GFP_KERNEL); 4498c2ecf20Sopenharmony_ci if (!card) 4508c2ecf20Sopenharmony_ci return -ENOMEM; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci card->cfg_base = chan->cfg_base; 4538c2ecf20Sopenharmony_ci card->reg_base = priv->reg_base; 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci card->led_chip.owner = THIS_MODULE; 4568c2ecf20Sopenharmony_ci card->led_chip.dev.parent = &pdev->dev; 4578c2ecf20Sopenharmony_ci card->led_chip.algo_data = &card->i2c_bit; 4588c2ecf20Sopenharmony_ci strncpy(card->led_chip.name, "peak_i2c", 4598c2ecf20Sopenharmony_ci sizeof(card->led_chip.name)); 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci card->i2c_bit = peak_pciec_i2c_bit_ops; 4628c2ecf20Sopenharmony_ci card->i2c_bit.udelay = 10; 4638c2ecf20Sopenharmony_ci card->i2c_bit.timeout = HZ; 4648c2ecf20Sopenharmony_ci card->i2c_bit.data = card; 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci peak_pciec_init_pita_gpio(card); 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci err = i2c_bit_add_bus(&card->led_chip); 4698c2ecf20Sopenharmony_ci if (err) { 4708c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "i2c init failed\n"); 4718c2ecf20Sopenharmony_ci goto pciec_init_err_1; 4728c2ecf20Sopenharmony_ci } 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci err = peak_pciec_init_leds(card); 4758c2ecf20Sopenharmony_ci if (err) { 4768c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "leds hardware init failed\n"); 4778c2ecf20Sopenharmony_ci goto pciec_init_err_2; 4788c2ecf20Sopenharmony_ci } 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&card->led_work, peak_pciec_led_work); 4818c2ecf20Sopenharmony_ci /* PCAN-ExpressCard needs its own callback for leds */ 4828c2ecf20Sopenharmony_ci priv->write_reg = peak_pciec_write_reg; 4838c2ecf20Sopenharmony_ci } 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci chan->pciec_card = card; 4868c2ecf20Sopenharmony_ci card->channel[card->chan_count++].netdev = dev; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci return 0; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_cipciec_init_err_2: 4918c2ecf20Sopenharmony_ci i2c_del_adapter(&card->led_chip); 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_cipciec_init_err_1: 4948c2ecf20Sopenharmony_ci peak_pciec_init_pita_gpio(card); 4958c2ecf20Sopenharmony_ci kfree(card); 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci return err; 4988c2ecf20Sopenharmony_ci} 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_cistatic void peak_pciec_remove(struct peak_pciec_card *card) 5018c2ecf20Sopenharmony_ci{ 5028c2ecf20Sopenharmony_ci peak_pciec_stop_led_work(card); 5038c2ecf20Sopenharmony_ci peak_pciec_leds_exit(card); 5048c2ecf20Sopenharmony_ci i2c_del_adapter(&card->led_chip); 5058c2ecf20Sopenharmony_ci peak_pciec_init_pita_gpio(card); 5068c2ecf20Sopenharmony_ci kfree(card); 5078c2ecf20Sopenharmony_ci} 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci#else /* CONFIG_CAN_PEAK_PCIEC */ 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci/* 5128c2ecf20Sopenharmony_ci * Placebo functions when PCAN-ExpressCard support is not selected 5138c2ecf20Sopenharmony_ci */ 5148c2ecf20Sopenharmony_cistatic inline int peak_pciec_probe(struct pci_dev *pdev, struct net_device *dev) 5158c2ecf20Sopenharmony_ci{ 5168c2ecf20Sopenharmony_ci return -ENODEV; 5178c2ecf20Sopenharmony_ci} 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_cistatic inline void peak_pciec_remove(struct peak_pciec_card *card) 5208c2ecf20Sopenharmony_ci{ 5218c2ecf20Sopenharmony_ci} 5228c2ecf20Sopenharmony_ci#endif /* CONFIG_CAN_PEAK_PCIEC */ 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_cistatic u8 peak_pci_read_reg(const struct sja1000_priv *priv, int port) 5258c2ecf20Sopenharmony_ci{ 5268c2ecf20Sopenharmony_ci return readb(priv->reg_base + (port << 2)); 5278c2ecf20Sopenharmony_ci} 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_cistatic void peak_pci_write_reg(const struct sja1000_priv *priv, 5308c2ecf20Sopenharmony_ci int port, u8 val) 5318c2ecf20Sopenharmony_ci{ 5328c2ecf20Sopenharmony_ci writeb(val, priv->reg_base + (port << 2)); 5338c2ecf20Sopenharmony_ci} 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_cistatic void peak_pci_post_irq(const struct sja1000_priv *priv) 5368c2ecf20Sopenharmony_ci{ 5378c2ecf20Sopenharmony_ci struct peak_pci_chan *chan = priv->priv; 5388c2ecf20Sopenharmony_ci u16 icr; 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci /* Select and clear in PITA stored interrupt */ 5418c2ecf20Sopenharmony_ci icr = readw(chan->cfg_base + PITA_ICR); 5428c2ecf20Sopenharmony_ci if (icr & chan->icr_mask) 5438c2ecf20Sopenharmony_ci writew(chan->icr_mask, chan->cfg_base + PITA_ICR); 5448c2ecf20Sopenharmony_ci} 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_cistatic int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 5478c2ecf20Sopenharmony_ci{ 5488c2ecf20Sopenharmony_ci struct sja1000_priv *priv; 5498c2ecf20Sopenharmony_ci struct peak_pci_chan *chan; 5508c2ecf20Sopenharmony_ci struct net_device *dev, *prev_dev; 5518c2ecf20Sopenharmony_ci void __iomem *cfg_base, *reg_base; 5528c2ecf20Sopenharmony_ci u16 sub_sys_id, icr; 5538c2ecf20Sopenharmony_ci int i, err, channels; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci err = pci_enable_device(pdev); 5568c2ecf20Sopenharmony_ci if (err) 5578c2ecf20Sopenharmony_ci return err; 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci err = pci_request_regions(pdev, DRV_NAME); 5608c2ecf20Sopenharmony_ci if (err) 5618c2ecf20Sopenharmony_ci goto failure_disable_pci; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci err = pci_read_config_word(pdev, 0x2e, &sub_sys_id); 5648c2ecf20Sopenharmony_ci if (err) 5658c2ecf20Sopenharmony_ci goto failure_release_regions; 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci dev_dbg(&pdev->dev, "probing device %04x:%04x:%04x\n", 5688c2ecf20Sopenharmony_ci pdev->vendor, pdev->device, sub_sys_id); 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci err = pci_write_config_word(pdev, 0x44, 0); 5718c2ecf20Sopenharmony_ci if (err) 5728c2ecf20Sopenharmony_ci goto failure_release_regions; 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci if (sub_sys_id >= 12) 5758c2ecf20Sopenharmony_ci channels = 4; 5768c2ecf20Sopenharmony_ci else if (sub_sys_id >= 10) 5778c2ecf20Sopenharmony_ci channels = 3; 5788c2ecf20Sopenharmony_ci else if (sub_sys_id >= 4) 5798c2ecf20Sopenharmony_ci channels = 2; 5808c2ecf20Sopenharmony_ci else 5818c2ecf20Sopenharmony_ci channels = 1; 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci cfg_base = pci_iomap(pdev, 0, PEAK_PCI_CFG_SIZE); 5848c2ecf20Sopenharmony_ci if (!cfg_base) { 5858c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to map PCI resource #0\n"); 5868c2ecf20Sopenharmony_ci err = -ENOMEM; 5878c2ecf20Sopenharmony_ci goto failure_release_regions; 5888c2ecf20Sopenharmony_ci } 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci reg_base = pci_iomap(pdev, 1, PEAK_PCI_CHAN_SIZE * channels); 5918c2ecf20Sopenharmony_ci if (!reg_base) { 5928c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to map PCI resource #1\n"); 5938c2ecf20Sopenharmony_ci err = -ENOMEM; 5948c2ecf20Sopenharmony_ci goto failure_unmap_cfg_base; 5958c2ecf20Sopenharmony_ci } 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci /* Set GPIO control register */ 5988c2ecf20Sopenharmony_ci writew(0x0005, cfg_base + PITA_GPIOICR + 2); 5998c2ecf20Sopenharmony_ci /* Enable all channels of this card */ 6008c2ecf20Sopenharmony_ci writeb(0x00, cfg_base + PITA_GPIOICR); 6018c2ecf20Sopenharmony_ci /* Toggle reset */ 6028c2ecf20Sopenharmony_ci writeb(0x05, cfg_base + PITA_MISC + 3); 6038c2ecf20Sopenharmony_ci usleep_range(5000, 6000); 6048c2ecf20Sopenharmony_ci /* Leave parport mux mode */ 6058c2ecf20Sopenharmony_ci writeb(0x04, cfg_base + PITA_MISC + 3); 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci icr = readw(cfg_base + PITA_ICR + 2); 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci for (i = 0; i < channels; i++) { 6108c2ecf20Sopenharmony_ci dev = alloc_sja1000dev(sizeof(struct peak_pci_chan)); 6118c2ecf20Sopenharmony_ci if (!dev) { 6128c2ecf20Sopenharmony_ci err = -ENOMEM; 6138c2ecf20Sopenharmony_ci goto failure_remove_channels; 6148c2ecf20Sopenharmony_ci } 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci priv = netdev_priv(dev); 6178c2ecf20Sopenharmony_ci chan = priv->priv; 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci chan->cfg_base = cfg_base; 6208c2ecf20Sopenharmony_ci priv->reg_base = reg_base + i * PEAK_PCI_CHAN_SIZE; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci priv->read_reg = peak_pci_read_reg; 6238c2ecf20Sopenharmony_ci priv->write_reg = peak_pci_write_reg; 6248c2ecf20Sopenharmony_ci priv->post_irq = peak_pci_post_irq; 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci priv->can.clock.freq = PEAK_PCI_CAN_CLOCK; 6278c2ecf20Sopenharmony_ci priv->ocr = PEAK_PCI_OCR; 6288c2ecf20Sopenharmony_ci priv->cdr = PEAK_PCI_CDR; 6298c2ecf20Sopenharmony_ci /* Neither a slave nor a single device distributes the clock */ 6308c2ecf20Sopenharmony_ci if (channels == 1 || i > 0) 6318c2ecf20Sopenharmony_ci priv->cdr |= CDR_CLK_OFF; 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci /* Setup interrupt handling */ 6348c2ecf20Sopenharmony_ci priv->irq_flags = IRQF_SHARED; 6358c2ecf20Sopenharmony_ci dev->irq = pdev->irq; 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci chan->icr_mask = peak_pci_icr_masks[i]; 6388c2ecf20Sopenharmony_ci icr |= chan->icr_mask; 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci SET_NETDEV_DEV(dev, &pdev->dev); 6418c2ecf20Sopenharmony_ci dev->dev_id = i; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci /* Create chain of SJA1000 devices */ 6448c2ecf20Sopenharmony_ci chan->prev_dev = pci_get_drvdata(pdev); 6458c2ecf20Sopenharmony_ci pci_set_drvdata(pdev, dev); 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci /* 6488c2ecf20Sopenharmony_ci * PCAN-ExpressCard needs some additional i2c init. 6498c2ecf20Sopenharmony_ci * This must be done *before* register_sja1000dev() but 6508c2ecf20Sopenharmony_ci * *after* devices linkage 6518c2ecf20Sopenharmony_ci */ 6528c2ecf20Sopenharmony_ci if (pdev->device == PEAK_PCIEC_DEVICE_ID || 6538c2ecf20Sopenharmony_ci pdev->device == PEAK_PCIEC34_DEVICE_ID) { 6548c2ecf20Sopenharmony_ci err = peak_pciec_probe(pdev, dev); 6558c2ecf20Sopenharmony_ci if (err) { 6568c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 6578c2ecf20Sopenharmony_ci "failed to probe device (err %d)\n", 6588c2ecf20Sopenharmony_ci err); 6598c2ecf20Sopenharmony_ci goto failure_free_dev; 6608c2ecf20Sopenharmony_ci } 6618c2ecf20Sopenharmony_ci } 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci err = register_sja1000dev(dev); 6648c2ecf20Sopenharmony_ci if (err) { 6658c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to register device\n"); 6668c2ecf20Sopenharmony_ci goto failure_free_dev; 6678c2ecf20Sopenharmony_ci } 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci dev_info(&pdev->dev, 6708c2ecf20Sopenharmony_ci "%s at reg_base=0x%p cfg_base=0x%p irq=%d\n", 6718c2ecf20Sopenharmony_ci dev->name, priv->reg_base, chan->cfg_base, dev->irq); 6728c2ecf20Sopenharmony_ci } 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci /* Enable interrupts */ 6758c2ecf20Sopenharmony_ci writew(icr, cfg_base + PITA_ICR + 2); 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci return 0; 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_cifailure_free_dev: 6808c2ecf20Sopenharmony_ci pci_set_drvdata(pdev, chan->prev_dev); 6818c2ecf20Sopenharmony_ci free_sja1000dev(dev); 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_cifailure_remove_channels: 6848c2ecf20Sopenharmony_ci /* Disable interrupts */ 6858c2ecf20Sopenharmony_ci writew(0x0, cfg_base + PITA_ICR + 2); 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci chan = NULL; 6888c2ecf20Sopenharmony_ci for (dev = pci_get_drvdata(pdev); dev; dev = prev_dev) { 6898c2ecf20Sopenharmony_ci priv = netdev_priv(dev); 6908c2ecf20Sopenharmony_ci chan = priv->priv; 6918c2ecf20Sopenharmony_ci prev_dev = chan->prev_dev; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci unregister_sja1000dev(dev); 6948c2ecf20Sopenharmony_ci free_sja1000dev(dev); 6958c2ecf20Sopenharmony_ci } 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci /* free any PCIeC resources too */ 6988c2ecf20Sopenharmony_ci if (chan && chan->pciec_card) 6998c2ecf20Sopenharmony_ci peak_pciec_remove(chan->pciec_card); 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci pci_iounmap(pdev, reg_base); 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_cifailure_unmap_cfg_base: 7048c2ecf20Sopenharmony_ci pci_iounmap(pdev, cfg_base); 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_cifailure_release_regions: 7078c2ecf20Sopenharmony_ci pci_release_regions(pdev); 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_cifailure_disable_pci: 7108c2ecf20Sopenharmony_ci pci_disable_device(pdev); 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci /* pci_xxx_config_word() return positive PCIBIOS_xxx error codes while 7138c2ecf20Sopenharmony_ci * the probe() function must return a negative errno in case of failure 7148c2ecf20Sopenharmony_ci * (err is unchanged if negative) */ 7158c2ecf20Sopenharmony_ci return pcibios_err_to_errno(err); 7168c2ecf20Sopenharmony_ci} 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_cistatic void peak_pci_remove(struct pci_dev *pdev) 7198c2ecf20Sopenharmony_ci{ 7208c2ecf20Sopenharmony_ci struct net_device *dev = pci_get_drvdata(pdev); /* Last device */ 7218c2ecf20Sopenharmony_ci struct sja1000_priv *priv = netdev_priv(dev); 7228c2ecf20Sopenharmony_ci struct peak_pci_chan *chan = priv->priv; 7238c2ecf20Sopenharmony_ci void __iomem *cfg_base = chan->cfg_base; 7248c2ecf20Sopenharmony_ci void __iomem *reg_base = priv->reg_base; 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci /* Disable interrupts */ 7278c2ecf20Sopenharmony_ci writew(0x0, cfg_base + PITA_ICR + 2); 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci /* Loop over all registered devices */ 7308c2ecf20Sopenharmony_ci while (1) { 7318c2ecf20Sopenharmony_ci struct net_device *prev_dev = chan->prev_dev; 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "removing device %s\n", dev->name); 7348c2ecf20Sopenharmony_ci /* do that only for first channel */ 7358c2ecf20Sopenharmony_ci if (!prev_dev && chan->pciec_card) 7368c2ecf20Sopenharmony_ci peak_pciec_remove(chan->pciec_card); 7378c2ecf20Sopenharmony_ci unregister_sja1000dev(dev); 7388c2ecf20Sopenharmony_ci free_sja1000dev(dev); 7398c2ecf20Sopenharmony_ci dev = prev_dev; 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci if (!dev) 7428c2ecf20Sopenharmony_ci break; 7438c2ecf20Sopenharmony_ci priv = netdev_priv(dev); 7448c2ecf20Sopenharmony_ci chan = priv->priv; 7458c2ecf20Sopenharmony_ci } 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci pci_iounmap(pdev, reg_base); 7488c2ecf20Sopenharmony_ci pci_iounmap(pdev, cfg_base); 7498c2ecf20Sopenharmony_ci pci_release_regions(pdev); 7508c2ecf20Sopenharmony_ci pci_disable_device(pdev); 7518c2ecf20Sopenharmony_ci} 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_cistatic struct pci_driver peak_pci_driver = { 7548c2ecf20Sopenharmony_ci .name = DRV_NAME, 7558c2ecf20Sopenharmony_ci .id_table = peak_pci_tbl, 7568c2ecf20Sopenharmony_ci .probe = peak_pci_probe, 7578c2ecf20Sopenharmony_ci .remove = peak_pci_remove, 7588c2ecf20Sopenharmony_ci}; 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_cimodule_pci_driver(peak_pci_driver); 761