| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205 |
- // SPDX-License-Identifier: GPL-2.0
- /* Fintek F81604 USB-to-2CAN controller driver.
- *
- * Copyright (C) 2023 Ji-Ze Hong (Peter Hong) <peter_hong@fintek.com.tw>
- */
- #include <linux/bitfield.h>
- #include <linux/netdevice.h>
- #include <linux/units.h>
- #include <linux/usb.h>
- #include <linux/can.h>
- #include <linux/can/dev.h>
- #include <linux/can/error.h>
- #include <linux/can/platform/sja1000.h>
- #include <linux/unaligned.h>
- /* vendor and product id */
- #define F81604_VENDOR_ID 0x2c42
- #define F81604_PRODUCT_ID 0x1709
- #define F81604_CAN_CLOCK (12 * MEGA)
- #define F81604_MAX_DEV 2
- #define F81604_SET_DEVICE_RETRY 10
- #define F81604_USB_TIMEOUT 2000
- #define F81604_SET_GET_REGISTER 0xA0
- #define F81604_PORT_OFFSET 0x1000
- #define F81604_MAX_RX_URBS 4
- #define F81604_CMD_DATA 0x00
- #define F81604_DLC_LEN_MASK GENMASK(3, 0)
- #define F81604_DLC_EFF_BIT BIT(7)
- #define F81604_DLC_RTR_BIT BIT(6)
- #define F81604_SFF_SHIFT 5
- #define F81604_EFF_SHIFT 3
- #define F81604_BRP_MASK GENMASK(5, 0)
- #define F81604_SJW_MASK GENMASK(7, 6)
- #define F81604_SEG1_MASK GENMASK(3, 0)
- #define F81604_SEG2_MASK GENMASK(6, 4)
- #define F81604_CLEAR_ALC 0
- #define F81604_CLEAR_ECC 1
- #define F81604_CLEAR_OVERRUN 2
- /* device setting */
- #define F81604_CTRL_MODE_REG 0x80
- #define F81604_TX_ONESHOT (0x03 << 3)
- #define F81604_TX_NORMAL (0x01 << 3)
- #define F81604_RX_AUTO_RELEASE_BUF BIT(1)
- #define F81604_INT_WHEN_CHANGE BIT(0)
- #define F81604_TERMINATOR_REG 0x105
- #define F81604_CAN0_TERM BIT(2)
- #define F81604_CAN1_TERM BIT(3)
- #define F81604_TERMINATION_DISABLED CAN_TERMINATION_DISABLED
- #define F81604_TERMINATION_ENABLED 120
- /* SJA1000 registers - manual section 6.4 (Pelican Mode) */
- #define F81604_SJA1000_MOD 0x00
- #define F81604_SJA1000_CMR 0x01
- #define F81604_SJA1000_IR 0x03
- #define F81604_SJA1000_IER 0x04
- #define F81604_SJA1000_ALC 0x0B
- #define F81604_SJA1000_ECC 0x0C
- #define F81604_SJA1000_RXERR 0x0E
- #define F81604_SJA1000_TXERR 0x0F
- #define F81604_SJA1000_ACCC0 0x10
- #define F81604_SJA1000_ACCM0 0x14
- #define F81604_MAX_FILTER_CNT 4
- /* Common registers - manual section 6.5 */
- #define F81604_SJA1000_BTR0 0x06
- #define F81604_SJA1000_BTR1 0x07
- #define F81604_SJA1000_BTR1_SAMPLE_TRIPLE BIT(7)
- #define F81604_SJA1000_OCR 0x08
- #define F81604_SJA1000_CDR 0x1F
- /* mode register */
- #define F81604_SJA1000_MOD_RM 0x01
- #define F81604_SJA1000_MOD_LOM 0x02
- #define F81604_SJA1000_MOD_STM 0x04
- /* commands */
- #define F81604_SJA1000_CMD_CDO 0x08
- /* interrupt sources */
- #define F81604_SJA1000_IRQ_BEI 0x80
- #define F81604_SJA1000_IRQ_ALI 0x40
- #define F81604_SJA1000_IRQ_EPI 0x20
- #define F81604_SJA1000_IRQ_DOI 0x08
- #define F81604_SJA1000_IRQ_EI 0x04
- #define F81604_SJA1000_IRQ_TI 0x02
- #define F81604_SJA1000_IRQ_RI 0x01
- #define F81604_SJA1000_IRQ_ALL 0xFF
- #define F81604_SJA1000_IRQ_OFF 0x00
- /* status register content */
- #define F81604_SJA1000_SR_BS 0x80
- #define F81604_SJA1000_SR_ES 0x40
- #define F81604_SJA1000_SR_TCS 0x08
- /* ECC register */
- #define F81604_SJA1000_ECC_SEG 0x1F
- #define F81604_SJA1000_ECC_DIR 0x20
- #define F81604_SJA1000_ECC_BIT 0x00
- #define F81604_SJA1000_ECC_FORM 0x40
- #define F81604_SJA1000_ECC_STUFF 0x80
- #define F81604_SJA1000_ECC_MASK 0xc0
- /* ALC register */
- #define F81604_SJA1000_ALC_MASK 0x1f
- /* table of devices that work with this driver */
- static const struct usb_device_id f81604_table[] = {
- { USB_DEVICE(F81604_VENDOR_ID, F81604_PRODUCT_ID) },
- {} /* Terminating entry */
- };
- MODULE_DEVICE_TABLE(usb, f81604_table);
- static const struct ethtool_ops f81604_ethtool_ops = {
- .get_ts_info = ethtool_op_get_ts_info,
- };
- static const u16 f81604_termination[] = { F81604_TERMINATION_DISABLED,
- F81604_TERMINATION_ENABLED };
- struct f81604_priv {
- struct net_device *netdev[F81604_MAX_DEV];
- };
- struct f81604_port_priv {
- struct can_priv can;
- struct net_device *netdev;
- struct sk_buff *echo_skb;
- unsigned long clear_flags;
- struct work_struct clear_reg_work;
- struct usb_device *dev;
- struct usb_interface *intf;
- struct usb_anchor urbs_anchor;
- };
- /* Interrupt endpoint data format:
- * Byte 0: Status register.
- * Byte 1: Interrupt register.
- * Byte 2: Interrupt enable register.
- * Byte 3: Arbitration lost capture(ALC) register.
- * Byte 4: Error code capture(ECC) register.
- * Byte 5: Error warning limit register.
- * Byte 6: RX error counter register.
- * Byte 7: TX error counter register.
- * Byte 8: Reserved.
- */
- struct f81604_int_data {
- u8 sr;
- u8 isrc;
- u8 ier;
- u8 alc;
- u8 ecc;
- u8 ewlr;
- u8 rxerr;
- u8 txerr;
- u8 val;
- } __packed __aligned(4);
- struct f81604_sff {
- __be16 id;
- u8 data[CAN_MAX_DLEN];
- } __packed __aligned(2);
- struct f81604_eff {
- __be32 id;
- u8 data[CAN_MAX_DLEN];
- } __packed __aligned(2);
- struct f81604_can_frame {
- u8 cmd;
- /* According for F81604 DLC define:
- * bit 3~0: data length (0~8)
- * bit6: is RTR flag.
- * bit7: is EFF frame.
- */
- u8 dlc;
- union {
- struct f81604_sff sff;
- struct f81604_eff eff;
- };
- } __packed __aligned(2);
- static const u8 bulk_in_addr[F81604_MAX_DEV] = { 2, 4 };
- static const u8 bulk_out_addr[F81604_MAX_DEV] = { 1, 3 };
- static const u8 int_in_addr[F81604_MAX_DEV] = { 1, 3 };
- static int f81604_write(struct usb_device *dev, u16 reg, u8 data)
- {
- int ret;
- ret = usb_control_msg_send(dev, 0, F81604_SET_GET_REGISTER,
- USB_TYPE_VENDOR | USB_DIR_OUT, 0, reg,
- &data, sizeof(data), F81604_USB_TIMEOUT,
- GFP_KERNEL);
- if (ret)
- dev_err(&dev->dev, "%s: reg: %x data: %x failed: %pe\n",
- __func__, reg, data, ERR_PTR(ret));
- return ret;
- }
- static int f81604_read(struct usb_device *dev, u16 reg, u8 *data)
- {
- int ret;
- ret = usb_control_msg_recv(dev, 0, F81604_SET_GET_REGISTER,
- USB_TYPE_VENDOR | USB_DIR_IN, 0, reg, data,
- sizeof(*data), F81604_USB_TIMEOUT,
- GFP_KERNEL);
- if (ret < 0)
- dev_err(&dev->dev, "%s: reg: %x failed: %pe\n", __func__, reg,
- ERR_PTR(ret));
- return ret;
- }
- static int f81604_update_bits(struct usb_device *dev, u16 reg, u8 mask,
- u8 data)
- {
- int ret;
- u8 tmp;
- ret = f81604_read(dev, reg, &tmp);
- if (ret)
- return ret;
- tmp &= ~mask;
- tmp |= (mask & data);
- return f81604_write(dev, reg, tmp);
- }
- static int f81604_sja1000_write(struct f81604_port_priv *priv, u16 reg,
- u8 data)
- {
- int port = priv->netdev->dev_port;
- int real_reg;
- real_reg = reg + F81604_PORT_OFFSET * port + F81604_PORT_OFFSET;
- return f81604_write(priv->dev, real_reg, data);
- }
- static int f81604_sja1000_read(struct f81604_port_priv *priv, u16 reg,
- u8 *data)
- {
- int port = priv->netdev->dev_port;
- int real_reg;
- real_reg = reg + F81604_PORT_OFFSET * port + F81604_PORT_OFFSET;
- return f81604_read(priv->dev, real_reg, data);
- }
- static int f81604_set_reset_mode(struct f81604_port_priv *priv)
- {
- int ret, i;
- u8 tmp;
- /* disable interrupts */
- ret = f81604_sja1000_write(priv, F81604_SJA1000_IER,
- F81604_SJA1000_IRQ_OFF);
- if (ret)
- return ret;
- for (i = 0; i < F81604_SET_DEVICE_RETRY; i++) {
- ret = f81604_sja1000_read(priv, F81604_SJA1000_MOD, &tmp);
- if (ret)
- return ret;
- /* check reset bit */
- if (tmp & F81604_SJA1000_MOD_RM) {
- priv->can.state = CAN_STATE_STOPPED;
- return 0;
- }
- /* reset chip */
- ret = f81604_sja1000_write(priv, F81604_SJA1000_MOD,
- F81604_SJA1000_MOD_RM);
- if (ret)
- return ret;
- }
- return -EPERM;
- }
- static int f81604_set_normal_mode(struct f81604_port_priv *priv)
- {
- u8 tmp, ier = 0;
- u8 mod_reg = 0;
- int ret, i;
- for (i = 0; i < F81604_SET_DEVICE_RETRY; i++) {
- ret = f81604_sja1000_read(priv, F81604_SJA1000_MOD, &tmp);
- if (ret)
- return ret;
- /* check reset bit */
- if ((tmp & F81604_SJA1000_MOD_RM) == 0) {
- priv->can.state = CAN_STATE_ERROR_ACTIVE;
- /* enable interrupts, RI handled by bulk-in */
- ier = F81604_SJA1000_IRQ_ALL & ~F81604_SJA1000_IRQ_RI;
- if (!(priv->can.ctrlmode &
- CAN_CTRLMODE_BERR_REPORTING))
- ier &= ~F81604_SJA1000_IRQ_BEI;
- return f81604_sja1000_write(priv, F81604_SJA1000_IER,
- ier);
- }
- /* set chip to normal mode */
- if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
- mod_reg |= F81604_SJA1000_MOD_LOM;
- if (priv->can.ctrlmode & CAN_CTRLMODE_PRESUME_ACK)
- mod_reg |= F81604_SJA1000_MOD_STM;
- ret = f81604_sja1000_write(priv, F81604_SJA1000_MOD, mod_reg);
- if (ret)
- return ret;
- }
- return -EPERM;
- }
- static int f81604_chipset_init(struct f81604_port_priv *priv)
- {
- int i, ret;
- /* set clock divider and output control register */
- ret = f81604_sja1000_write(priv, F81604_SJA1000_CDR,
- CDR_CBP | CDR_PELICAN);
- if (ret)
- return ret;
- /* set acceptance filter (accept all) */
- for (i = 0; i < F81604_MAX_FILTER_CNT; ++i) {
- ret = f81604_sja1000_write(priv, F81604_SJA1000_ACCC0 + i, 0);
- if (ret)
- return ret;
- }
- for (i = 0; i < F81604_MAX_FILTER_CNT; ++i) {
- ret = f81604_sja1000_write(priv, F81604_SJA1000_ACCM0 + i,
- 0xFF);
- if (ret)
- return ret;
- }
- return f81604_sja1000_write(priv, F81604_SJA1000_OCR,
- OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL |
- OCR_MODE_NORMAL);
- }
- static void f81604_process_rx_packet(struct net_device *netdev,
- struct f81604_can_frame *frame)
- {
- struct net_device_stats *stats = &netdev->stats;
- struct can_frame *cf;
- struct sk_buff *skb;
- if (frame->cmd != F81604_CMD_DATA)
- return;
- skb = alloc_can_skb(netdev, &cf);
- if (!skb) {
- stats->rx_dropped++;
- return;
- }
- cf->len = can_cc_dlc2len(frame->dlc & F81604_DLC_LEN_MASK);
- if (frame->dlc & F81604_DLC_EFF_BIT) {
- cf->can_id = get_unaligned_be32(&frame->eff.id) >>
- F81604_EFF_SHIFT;
- cf->can_id |= CAN_EFF_FLAG;
- if (!(frame->dlc & F81604_DLC_RTR_BIT))
- memcpy(cf->data, frame->eff.data, cf->len);
- } else {
- cf->can_id = get_unaligned_be16(&frame->sff.id) >>
- F81604_SFF_SHIFT;
- if (!(frame->dlc & F81604_DLC_RTR_BIT))
- memcpy(cf->data, frame->sff.data, cf->len);
- }
- if (frame->dlc & F81604_DLC_RTR_BIT)
- cf->can_id |= CAN_RTR_FLAG;
- else
- stats->rx_bytes += cf->len;
- stats->rx_packets++;
- netif_rx(skb);
- }
- static void f81604_read_bulk_callback(struct urb *urb)
- {
- struct f81604_can_frame *frame = urb->transfer_buffer;
- struct net_device *netdev = urb->context;
- int ret;
- if (!netif_device_present(netdev))
- return;
- if (urb->status)
- netdev_info(netdev, "%s: URB aborted %pe\n", __func__,
- ERR_PTR(urb->status));
- switch (urb->status) {
- case 0: /* success */
- break;
- case -ENOENT:
- case -EPIPE:
- case -EPROTO:
- case -ESHUTDOWN:
- return;
- default:
- goto resubmit_urb;
- }
- if (urb->actual_length != sizeof(*frame)) {
- netdev_warn(netdev, "URB length %u not equal to %zu\n",
- urb->actual_length, sizeof(*frame));
- goto resubmit_urb;
- }
- f81604_process_rx_packet(netdev, frame);
- resubmit_urb:
- ret = usb_submit_urb(urb, GFP_ATOMIC);
- if (ret == -ENODEV)
- netif_device_detach(netdev);
- else if (ret)
- netdev_err(netdev,
- "%s: failed to resubmit read bulk urb: %pe\n",
- __func__, ERR_PTR(ret));
- }
- static void f81604_handle_tx(struct f81604_port_priv *priv,
- struct f81604_int_data *data)
- {
- struct net_device *netdev = priv->netdev;
- struct net_device_stats *stats = &netdev->stats;
- /* transmission buffer released */
- if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT &&
- !(data->sr & F81604_SJA1000_SR_TCS)) {
- stats->tx_errors++;
- can_free_echo_skb(netdev, 0, NULL);
- } else {
- /* transmission complete */
- stats->tx_bytes += can_get_echo_skb(netdev, 0, NULL);
- stats->tx_packets++;
- }
- netif_wake_queue(netdev);
- }
- static void f81604_handle_can_bus_errors(struct f81604_port_priv *priv,
- struct f81604_int_data *data)
- {
- enum can_state can_state = priv->can.state;
- struct net_device *netdev = priv->netdev;
- struct net_device_stats *stats = &netdev->stats;
- struct can_frame *cf;
- struct sk_buff *skb;
- /* Note: ALC/ECC will not auto clear by read here, must be cleared by
- * read register (via clear_reg_work).
- */
- skb = alloc_can_err_skb(netdev, &cf);
- if (skb) {
- cf->can_id |= CAN_ERR_CNT;
- cf->data[6] = data->txerr;
- cf->data[7] = data->rxerr;
- }
- if (data->isrc & F81604_SJA1000_IRQ_DOI) {
- /* data overrun interrupt */
- netdev_dbg(netdev, "data overrun interrupt\n");
- if (skb) {
- cf->can_id |= CAN_ERR_CRTL;
- cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
- }
- stats->rx_over_errors++;
- stats->rx_errors++;
- set_bit(F81604_CLEAR_OVERRUN, &priv->clear_flags);
- }
- if (data->isrc & F81604_SJA1000_IRQ_EI) {
- /* error warning interrupt */
- netdev_dbg(netdev, "error warning interrupt\n");
- if (data->sr & F81604_SJA1000_SR_BS)
- can_state = CAN_STATE_BUS_OFF;
- else if (data->sr & F81604_SJA1000_SR_ES)
- can_state = CAN_STATE_ERROR_WARNING;
- else
- can_state = CAN_STATE_ERROR_ACTIVE;
- }
- if (data->isrc & F81604_SJA1000_IRQ_BEI) {
- /* bus error interrupt */
- netdev_dbg(netdev, "bus error interrupt\n");
- priv->can.can_stats.bus_error++;
- if (skb) {
- cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
- /* set error type */
- switch (data->ecc & F81604_SJA1000_ECC_MASK) {
- case F81604_SJA1000_ECC_BIT:
- cf->data[2] |= CAN_ERR_PROT_BIT;
- break;
- case F81604_SJA1000_ECC_FORM:
- cf->data[2] |= CAN_ERR_PROT_FORM;
- break;
- case F81604_SJA1000_ECC_STUFF:
- cf->data[2] |= CAN_ERR_PROT_STUFF;
- break;
- default:
- break;
- }
- /* set error location */
- cf->data[3] = data->ecc & F81604_SJA1000_ECC_SEG;
- }
- /* Error occurred during transmission? */
- if ((data->ecc & F81604_SJA1000_ECC_DIR) == 0) {
- stats->tx_errors++;
- if (skb)
- cf->data[2] |= CAN_ERR_PROT_TX;
- } else {
- stats->rx_errors++;
- }
- set_bit(F81604_CLEAR_ECC, &priv->clear_flags);
- }
- if (data->isrc & F81604_SJA1000_IRQ_EPI) {
- if (can_state == CAN_STATE_ERROR_PASSIVE)
- can_state = CAN_STATE_ERROR_WARNING;
- else
- can_state = CAN_STATE_ERROR_PASSIVE;
- /* error passive interrupt */
- netdev_dbg(netdev, "error passive interrupt: %d\n", can_state);
- }
- if (data->isrc & F81604_SJA1000_IRQ_ALI) {
- /* arbitration lost interrupt */
- netdev_dbg(netdev, "arbitration lost interrupt\n");
- priv->can.can_stats.arbitration_lost++;
- if (skb) {
- cf->can_id |= CAN_ERR_LOSTARB;
- cf->data[0] = data->alc & F81604_SJA1000_ALC_MASK;
- }
- set_bit(F81604_CLEAR_ALC, &priv->clear_flags);
- }
- if (can_state != priv->can.state) {
- enum can_state tx_state, rx_state;
- tx_state = data->txerr >= data->rxerr ? can_state : 0;
- rx_state = data->txerr <= data->rxerr ? can_state : 0;
- can_change_state(netdev, cf, tx_state, rx_state);
- if (can_state == CAN_STATE_BUS_OFF)
- can_bus_off(netdev);
- }
- if (priv->clear_flags)
- schedule_work(&priv->clear_reg_work);
- if (skb)
- netif_rx(skb);
- }
- static void f81604_read_int_callback(struct urb *urb)
- {
- struct f81604_int_data *data = urb->transfer_buffer;
- struct net_device *netdev = urb->context;
- struct f81604_port_priv *priv;
- int ret;
- priv = netdev_priv(netdev);
- if (!netif_device_present(netdev))
- return;
- if (urb->status)
- netdev_info(netdev, "%s: Int URB aborted: %pe\n", __func__,
- ERR_PTR(urb->status));
- switch (urb->status) {
- case 0: /* success */
- break;
- case -ENOENT:
- case -EPIPE:
- case -EPROTO:
- case -ESHUTDOWN:
- return;
- default:
- goto resubmit_urb;
- }
- /* handle Errors */
- if (data->isrc & (F81604_SJA1000_IRQ_DOI | F81604_SJA1000_IRQ_EI |
- F81604_SJA1000_IRQ_BEI | F81604_SJA1000_IRQ_EPI |
- F81604_SJA1000_IRQ_ALI))
- f81604_handle_can_bus_errors(priv, data);
- /* handle TX */
- if (priv->can.state != CAN_STATE_BUS_OFF &&
- (data->isrc & F81604_SJA1000_IRQ_TI))
- f81604_handle_tx(priv, data);
- resubmit_urb:
- ret = usb_submit_urb(urb, GFP_ATOMIC);
- if (ret == -ENODEV)
- netif_device_detach(netdev);
- else if (ret)
- netdev_err(netdev, "%s: failed to resubmit int urb: %pe\n",
- __func__, ERR_PTR(ret));
- }
- static void f81604_unregister_urbs(struct f81604_port_priv *priv)
- {
- usb_kill_anchored_urbs(&priv->urbs_anchor);
- }
- static int f81604_register_urbs(struct f81604_port_priv *priv)
- {
- struct net_device *netdev = priv->netdev;
- struct f81604_int_data *int_data;
- int id = netdev->dev_port;
- struct urb *int_urb;
- int rx_urb_cnt;
- int ret;
- for (rx_urb_cnt = 0; rx_urb_cnt < F81604_MAX_RX_URBS; ++rx_urb_cnt) {
- struct f81604_can_frame *frame;
- struct urb *rx_urb;
- rx_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!rx_urb) {
- ret = -ENOMEM;
- break;
- }
- frame = kmalloc(sizeof(*frame), GFP_KERNEL);
- if (!frame) {
- usb_free_urb(rx_urb);
- ret = -ENOMEM;
- break;
- }
- usb_fill_bulk_urb(rx_urb, priv->dev,
- usb_rcvbulkpipe(priv->dev, bulk_in_addr[id]),
- frame, sizeof(*frame),
- f81604_read_bulk_callback, netdev);
- rx_urb->transfer_flags |= URB_FREE_BUFFER;
- usb_anchor_urb(rx_urb, &priv->urbs_anchor);
- ret = usb_submit_urb(rx_urb, GFP_KERNEL);
- if (ret) {
- usb_unanchor_urb(rx_urb);
- usb_free_urb(rx_urb);
- break;
- }
- /* Drop reference, USB core will take care of freeing it */
- usb_free_urb(rx_urb);
- }
- if (rx_urb_cnt == 0) {
- netdev_warn(netdev, "%s: submit rx urb failed: %pe\n",
- __func__, ERR_PTR(ret));
- goto error;
- }
- int_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!int_urb) {
- ret = -ENOMEM;
- goto error;
- }
- int_data = kmalloc(sizeof(*int_data), GFP_KERNEL);
- if (!int_data) {
- usb_free_urb(int_urb);
- ret = -ENOMEM;
- goto error;
- }
- usb_fill_int_urb(int_urb, priv->dev,
- usb_rcvintpipe(priv->dev, int_in_addr[id]), int_data,
- sizeof(*int_data), f81604_read_int_callback, netdev,
- 1);
- int_urb->transfer_flags |= URB_FREE_BUFFER;
- usb_anchor_urb(int_urb, &priv->urbs_anchor);
- ret = usb_submit_urb(int_urb, GFP_KERNEL);
- if (ret) {
- usb_unanchor_urb(int_urb);
- usb_free_urb(int_urb);
- netdev_warn(netdev, "%s: submit int urb failed: %pe\n",
- __func__, ERR_PTR(ret));
- goto error;
- }
- /* Drop reference, USB core will take care of freeing it */
- usb_free_urb(int_urb);
- return 0;
- error:
- f81604_unregister_urbs(priv);
- return ret;
- }
- static int f81604_start(struct net_device *netdev)
- {
- struct f81604_port_priv *priv = netdev_priv(netdev);
- int ret;
- u8 mode;
- u8 tmp;
- mode = F81604_RX_AUTO_RELEASE_BUF | F81604_INT_WHEN_CHANGE;
- /* Set TR/AT mode */
- if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
- mode |= F81604_TX_ONESHOT;
- else
- mode |= F81604_TX_NORMAL;
- ret = f81604_sja1000_write(priv, F81604_CTRL_MODE_REG, mode);
- if (ret)
- return ret;
- /* set reset mode */
- ret = f81604_set_reset_mode(priv);
- if (ret)
- return ret;
- ret = f81604_chipset_init(priv);
- if (ret)
- return ret;
- /* Clear error counters and error code capture */
- ret = f81604_sja1000_write(priv, F81604_SJA1000_TXERR, 0);
- if (ret)
- return ret;
- ret = f81604_sja1000_write(priv, F81604_SJA1000_RXERR, 0);
- if (ret)
- return ret;
- /* Read clear for ECC/ALC/IR register */
- ret = f81604_sja1000_read(priv, F81604_SJA1000_ECC, &tmp);
- if (ret)
- return ret;
- ret = f81604_sja1000_read(priv, F81604_SJA1000_ALC, &tmp);
- if (ret)
- return ret;
- ret = f81604_sja1000_read(priv, F81604_SJA1000_IR, &tmp);
- if (ret)
- return ret;
- ret = f81604_register_urbs(priv);
- if (ret)
- return ret;
- ret = f81604_set_normal_mode(priv);
- if (ret) {
- f81604_unregister_urbs(priv);
- return ret;
- }
- return 0;
- }
- static int f81604_set_bittiming(struct net_device *dev)
- {
- struct f81604_port_priv *priv = netdev_priv(dev);
- struct can_bittiming *bt = &priv->can.bittiming;
- u8 btr0, btr1;
- int ret;
- btr0 = FIELD_PREP(F81604_BRP_MASK, bt->brp - 1) |
- FIELD_PREP(F81604_SJW_MASK, bt->sjw - 1);
- btr1 = FIELD_PREP(F81604_SEG1_MASK,
- bt->prop_seg + bt->phase_seg1 - 1) |
- FIELD_PREP(F81604_SEG2_MASK, bt->phase_seg2 - 1);
- if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
- btr1 |= F81604_SJA1000_BTR1_SAMPLE_TRIPLE;
- ret = f81604_sja1000_write(priv, F81604_SJA1000_BTR0, btr0);
- if (ret) {
- netdev_warn(dev, "%s: Set BTR0 failed: %pe\n", __func__,
- ERR_PTR(ret));
- return ret;
- }
- ret = f81604_sja1000_write(priv, F81604_SJA1000_BTR1, btr1);
- if (ret) {
- netdev_warn(dev, "%s: Set BTR1 failed: %pe\n", __func__,
- ERR_PTR(ret));
- return ret;
- }
- return 0;
- }
- static int f81604_set_mode(struct net_device *netdev, enum can_mode mode)
- {
- int ret;
- switch (mode) {
- case CAN_MODE_START:
- ret = f81604_start(netdev);
- if (!ret && netif_queue_stopped(netdev))
- netif_wake_queue(netdev);
- break;
- default:
- ret = -EOPNOTSUPP;
- }
- return ret;
- }
- static void f81604_write_bulk_callback(struct urb *urb)
- {
- struct net_device *netdev = urb->context;
- if (!netif_device_present(netdev))
- return;
- if (urb->status)
- netdev_info(netdev, "%s: Tx URB error: %pe\n", __func__,
- ERR_PTR(urb->status));
- }
- static void f81604_clear_reg_work(struct work_struct *work)
- {
- struct f81604_port_priv *priv;
- u8 tmp;
- priv = container_of(work, struct f81604_port_priv, clear_reg_work);
- /* dummy read for clear Arbitration lost capture(ALC) register. */
- if (test_and_clear_bit(F81604_CLEAR_ALC, &priv->clear_flags))
- f81604_sja1000_read(priv, F81604_SJA1000_ALC, &tmp);
- /* dummy read for clear Error code capture(ECC) register. */
- if (test_and_clear_bit(F81604_CLEAR_ECC, &priv->clear_flags))
- f81604_sja1000_read(priv, F81604_SJA1000_ECC, &tmp);
- /* dummy write for clear data overrun flag. */
- if (test_and_clear_bit(F81604_CLEAR_OVERRUN, &priv->clear_flags))
- f81604_sja1000_write(priv, F81604_SJA1000_CMR,
- F81604_SJA1000_CMD_CDO);
- }
- static netdev_tx_t f81604_start_xmit(struct sk_buff *skb,
- struct net_device *netdev)
- {
- struct can_frame *cf = (struct can_frame *)skb->data;
- struct f81604_port_priv *priv = netdev_priv(netdev);
- struct net_device_stats *stats = &netdev->stats;
- struct f81604_can_frame *frame;
- struct urb *write_urb;
- int ret;
- if (can_dev_dropped_skb(netdev, skb))
- return NETDEV_TX_OK;
- netif_stop_queue(netdev);
- write_urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!write_urb)
- goto nomem_urb;
- frame = kzalloc(sizeof(*frame), GFP_ATOMIC);
- if (!frame)
- goto nomem_buf;
- usb_fill_bulk_urb(write_urb, priv->dev,
- usb_sndbulkpipe(priv->dev,
- bulk_out_addr[netdev->dev_port]),
- frame, sizeof(*frame), f81604_write_bulk_callback,
- priv->netdev);
- write_urb->transfer_flags |= URB_FREE_BUFFER;
- frame->cmd = F81604_CMD_DATA;
- frame->dlc = cf->len;
- if (cf->can_id & CAN_RTR_FLAG)
- frame->dlc |= F81604_DLC_RTR_BIT;
- if (cf->can_id & CAN_EFF_FLAG) {
- u32 id = (cf->can_id & CAN_EFF_MASK) << F81604_EFF_SHIFT;
- put_unaligned_be32(id, &frame->eff.id);
- frame->dlc |= F81604_DLC_EFF_BIT;
- if (!(cf->can_id & CAN_RTR_FLAG))
- memcpy(&frame->eff.data, cf->data, cf->len);
- } else {
- u32 id = (cf->can_id & CAN_SFF_MASK) << F81604_SFF_SHIFT;
- put_unaligned_be16(id, &frame->sff.id);
- if (!(cf->can_id & CAN_RTR_FLAG))
- memcpy(&frame->sff.data, cf->data, cf->len);
- }
- can_put_echo_skb(skb, netdev, 0, 0);
- ret = usb_submit_urb(write_urb, GFP_ATOMIC);
- if (ret) {
- netdev_err(netdev, "%s: failed to resubmit tx bulk urb: %pe\n",
- __func__, ERR_PTR(ret));
- can_free_echo_skb(netdev, 0, NULL);
- stats->tx_dropped++;
- stats->tx_errors++;
- if (ret == -ENODEV)
- netif_device_detach(netdev);
- else
- netif_wake_queue(netdev);
- }
- /* let usb core take care of this urb */
- usb_free_urb(write_urb);
- return NETDEV_TX_OK;
- nomem_buf:
- usb_free_urb(write_urb);
- nomem_urb:
- dev_kfree_skb(skb);
- stats->tx_dropped++;
- stats->tx_errors++;
- netif_wake_queue(netdev);
- return NETDEV_TX_OK;
- }
- static int f81604_get_berr_counter(const struct net_device *netdev,
- struct can_berr_counter *bec)
- {
- struct f81604_port_priv *priv = netdev_priv(netdev);
- u8 txerr, rxerr;
- int ret;
- ret = f81604_sja1000_read(priv, F81604_SJA1000_TXERR, &txerr);
- if (ret)
- return ret;
- ret = f81604_sja1000_read(priv, F81604_SJA1000_RXERR, &rxerr);
- if (ret)
- return ret;
- bec->txerr = txerr;
- bec->rxerr = rxerr;
- return 0;
- }
- /* Open USB device */
- static int f81604_open(struct net_device *netdev)
- {
- int ret;
- ret = open_candev(netdev);
- if (ret)
- return ret;
- ret = f81604_start(netdev);
- if (ret) {
- if (ret == -ENODEV)
- netif_device_detach(netdev);
- close_candev(netdev);
- return ret;
- }
- netif_start_queue(netdev);
- return 0;
- }
- /* Close USB device */
- static int f81604_close(struct net_device *netdev)
- {
- struct f81604_port_priv *priv = netdev_priv(netdev);
- f81604_set_reset_mode(priv);
- netif_stop_queue(netdev);
- cancel_work_sync(&priv->clear_reg_work);
- close_candev(netdev);
- f81604_unregister_urbs(priv);
- return 0;
- }
- static const struct net_device_ops f81604_netdev_ops = {
- .ndo_open = f81604_open,
- .ndo_stop = f81604_close,
- .ndo_start_xmit = f81604_start_xmit,
- .ndo_change_mtu = can_change_mtu,
- };
- static const struct can_bittiming_const f81604_bittiming_const = {
- .name = KBUILD_MODNAME,
- .tseg1_min = 1,
- .tseg1_max = 16,
- .tseg2_min = 1,
- .tseg2_max = 8,
- .sjw_max = 4,
- .brp_min = 1,
- .brp_max = 64,
- .brp_inc = 1,
- };
- /* Called by the usb core when driver is unloaded or device is removed */
- static void f81604_disconnect(struct usb_interface *intf)
- {
- struct f81604_priv *priv = usb_get_intfdata(intf);
- int i;
- for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) {
- if (!priv->netdev[i])
- continue;
- unregister_netdev(priv->netdev[i]);
- free_candev(priv->netdev[i]);
- }
- }
- static int __f81604_set_termination(struct usb_device *dev, int idx, u16 term)
- {
- u8 mask, data = 0;
- if (idx == 0)
- mask = F81604_CAN0_TERM;
- else
- mask = F81604_CAN1_TERM;
- if (term)
- data = mask;
- return f81604_update_bits(dev, F81604_TERMINATOR_REG, mask, data);
- }
- static int f81604_set_termination(struct net_device *netdev, u16 term)
- {
- struct f81604_port_priv *port_priv = netdev_priv(netdev);
- ASSERT_RTNL();
- return __f81604_set_termination(port_priv->dev, netdev->dev_port,
- term);
- }
- static int f81604_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
- {
- struct usb_device *dev = interface_to_usbdev(intf);
- struct net_device *netdev;
- struct f81604_priv *priv;
- int i, ret;
- priv = devm_kzalloc(&intf->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
- usb_set_intfdata(intf, priv);
- for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) {
- ret = __f81604_set_termination(dev, i, 0);
- if (ret) {
- dev_err(&intf->dev,
- "Setting termination of CH#%d failed: %pe\n",
- i, ERR_PTR(ret));
- return ret;
- }
- }
- for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) {
- struct f81604_port_priv *port_priv;
- netdev = alloc_candev(sizeof(*port_priv), 1);
- if (!netdev) {
- dev_err(&intf->dev, "Couldn't alloc candev: %d\n", i);
- ret = -ENOMEM;
- goto failure_cleanup;
- }
- port_priv = netdev_priv(netdev);
- INIT_WORK(&port_priv->clear_reg_work, f81604_clear_reg_work);
- init_usb_anchor(&port_priv->urbs_anchor);
- port_priv->intf = intf;
- port_priv->dev = dev;
- port_priv->netdev = netdev;
- port_priv->can.clock.freq = F81604_CAN_CLOCK;
- port_priv->can.termination_const = f81604_termination;
- port_priv->can.termination_const_cnt =
- ARRAY_SIZE(f81604_termination);
- port_priv->can.bittiming_const = &f81604_bittiming_const;
- port_priv->can.do_set_bittiming = f81604_set_bittiming;
- port_priv->can.do_set_mode = f81604_set_mode;
- port_priv->can.do_set_termination = f81604_set_termination;
- port_priv->can.do_get_berr_counter = f81604_get_berr_counter;
- port_priv->can.ctrlmode_supported =
- CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_3_SAMPLES |
- CAN_CTRLMODE_ONE_SHOT | CAN_CTRLMODE_BERR_REPORTING |
- CAN_CTRLMODE_PRESUME_ACK;
- netdev->ethtool_ops = &f81604_ethtool_ops;
- netdev->netdev_ops = &f81604_netdev_ops;
- netdev->flags |= IFF_ECHO;
- netdev->dev_port = i;
- SET_NETDEV_DEV(netdev, &intf->dev);
- ret = register_candev(netdev);
- if (ret) {
- netdev_err(netdev, "register CAN device failed: %pe\n",
- ERR_PTR(ret));
- free_candev(netdev);
- goto failure_cleanup;
- }
- priv->netdev[i] = netdev;
- }
- return 0;
- failure_cleanup:
- f81604_disconnect(intf);
- return ret;
- }
- static struct usb_driver f81604_driver = {
- .name = KBUILD_MODNAME,
- .probe = f81604_probe,
- .disconnect = f81604_disconnect,
- .id_table = f81604_table,
- };
- module_usb_driver(f81604_driver);
- MODULE_AUTHOR("Ji-Ze Hong (Peter Hong) <peter_hong@fintek.com.tw>");
- MODULE_DESCRIPTION("Fintek F81604 USB to 2xCANBUS");
- MODULE_LICENSE("GPL");
|