Commit 36026fff authored by Pavel Pisa's avatar Pavel Pisa
Browse files

driver: separate common registration code from platform driver specific one.


Signed-off-by: Pavel Pisa's avatarPavel Pisa <pisa@cmp.felk.cvut.cz>
parent e262315f
...@@ -903,37 +903,28 @@ static const struct dev_pm_ops ctucan_dev_pm_ops = { ...@@ -903,37 +903,28 @@ static const struct dev_pm_ops ctucan_dev_pm_ops = {
/** /**
* ctucan_probe - Platform registration call * ctucan_probe_common - Device type independent registration call
* @pdev: Handle to the platform device structure
* *
* This function does all the memory allocation and registration for the CAN * This function does all the memory allocation and registration for the CAN
* device. * device.
* *
* @dev: Handle to the generic device structure
* @addr: Base address of CTU CAN FD core address
* @irq: Interrupt number
* @ntxbufs: Number of implemented Tx buffers
* @can_clk_rate: Clock rate, if 0 then clock are taken from device node
* @set_drvdata_fnc: Function to set network driver data for physical device
*
* Return: 0 on success and failure value on error * Return: 0 on success and failure value on error
*/ */
static int ctucan_probe(struct platform_device *pdev) static int ctucan_probe_common(struct device *dev, void __iomem *addr,
int irq, unsigned int ntxbufs, unsigned long can_clk_rate,
void (*set_drvdata_fnc)(struct device *dev,
struct net_device *ndev))
{ {
struct resource *res; /* IO mem resources */
struct net_device *ndev;
struct ctucan_priv *priv; struct ctucan_priv *priv;
void __iomem *addr; struct net_device *ndev;
int ret; int ret;
unsigned int ntxbufs;
/* Get the virtual base address for the device */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
addr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(addr)) {
ret = PTR_ERR(addr);
goto err;
}
/*
ret = of_property_read_u32(pdev->dev.of_node, "tx-fifo-depth", &tx_max);
if (ret < 0)
goto err;
*/
ntxbufs = 4;
/* Create a CAN device instance */ /* Create a CAN device instance */
ndev = alloc_candev(sizeof(struct ctucan_priv), ntxbufs); ndev = alloc_candev(sizeof(struct ctucan_priv), ntxbufs);
...@@ -942,7 +933,7 @@ static int ctucan_probe(struct platform_device *pdev) ...@@ -942,7 +933,7 @@ static int ctucan_probe(struct platform_device *pdev)
priv = netdev_priv(ndev); priv = netdev_priv(ndev);
priv->txb_mask = ntxbufs-1; priv->txb_mask = ntxbufs-1;
priv->dev = &pdev->dev; priv->dev = dev;
priv->can.bittiming_const = &ctu_can_fd_bit_timing_max; priv->can.bittiming_const = &ctu_can_fd_bit_timing_max;
priv->can.data_bittiming_const = &ctu_can_fd_bit_timing_data_max; priv->can.data_bittiming_const = &ctu_can_fd_bit_timing_data_max;
priv->can.do_set_mode = ctucan_do_set_mode; priv->can.do_set_mode = ctucan_do_set_mode;
...@@ -963,54 +954,64 @@ static int ctucan_probe(struct platform_device *pdev) ...@@ -963,54 +954,64 @@ static int ctucan_probe(struct platform_device *pdev)
priv->p.mem_base = addr; priv->p.mem_base = addr;
/* Get IRQ for the device */ /* Get IRQ for the device */
ndev->irq = platform_get_irq(pdev, 0); ndev->irq = irq;
ndev->flags |= IFF_ECHO; /* We support local echo */ ndev->flags |= IFF_ECHO; /* We support local echo */
platform_set_drvdata(pdev, ndev); if (set_drvdata_fnc != NULL)
SET_NETDEV_DEV(ndev, &pdev->dev); set_drvdata_fnc(dev, ndev);
SET_NETDEV_DEV(ndev, dev);
ndev->netdev_ops = &ctucan_netdev_ops; ndev->netdev_ops = &ctucan_netdev_ops;
/* Getting the CAN can_clk info */ /* Getting the CAN can_clk info */
priv->can_clk = devm_clk_get(&pdev->dev, NULL); if (can_clk_rate == 0) {
if (IS_ERR(priv->can_clk)) { priv->can_clk = devm_clk_get(dev, NULL);
dev_err(&pdev->dev, "Device clock not found.\n"); if (IS_ERR(priv->can_clk)) {
ret = PTR_ERR(priv->can_clk); dev_err(dev, "Device clock not found.\n");
goto err_free; ret = PTR_ERR(priv->can_clk);
goto err_free;
}
can_clk_rate = clk_get_rate(priv->can_clk);
} }
priv->p.write_reg = ctu_can_fd_write32; priv->p.write_reg = ctu_can_fd_write32;
priv->p.read_reg = ctu_can_fd_read32; priv->p.read_reg = ctu_can_fd_read32;
pm_runtime_enable(&pdev->dev); pm_runtime_enable(dev);
ret = pm_runtime_get_sync(&pdev->dev); ret = pm_runtime_get_sync(dev);
if (ret < 0) { if (ret < 0) {
netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",
__func__, ret); __func__, ret);
goto err_pmdisable; goto err_pmdisable;
} }
if ((priv->p.read_reg(&priv->p, CTU_CAN_FD_DEVICE_ID) & 0xFFFF) != CTU_CAN_FD_ID) { if ((priv->p.read_reg(&priv->p, CTU_CAN_FD_DEVICE_ID) &
0xFFFF) != CTU_CAN_FD_ID) {
priv->p.write_reg = ctu_can_fd_write32_be; priv->p.write_reg = ctu_can_fd_write32_be;
priv->p.read_reg = ctu_can_fd_read32_be; priv->p.read_reg = ctu_can_fd_read32_be;
if ((priv->p.read_reg(&priv->p, CTU_CAN_FD_DEVICE_ID) &
0xFFFF) != CTU_CAN_FD_ID) {
netdev_err(ndev, "CTU_CAN_FD signature not found\n");
goto err_pmdisable;
}
} }
ret = ctucan_reset(ndev); ret = ctucan_reset(ndev);
if (ret < 0) if (ret < 0)
goto err_pmdisable; goto err_pmdisable;
priv->can.clock.freq = clk_get_rate(priv->can_clk); priv->can.clock.freq = can_clk_rate;
netif_napi_add(ndev, &priv->napi, ctucan_rx_poll, NAPI_POLL_WEIGHT); netif_napi_add(ndev, &priv->napi, ctucan_rx_poll, NAPI_POLL_WEIGHT);
ret = register_candev(ndev); ret = register_candev(ndev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "fail to register failed (err=%d)\n", ret); dev_err(dev, "fail to register failed (err=%d)\n", ret);
goto err_disableclks; goto err_disableclks;
} }
devm_can_led_init(ndev); devm_can_led_init(ndev);
pm_runtime_put(&pdev->dev); pm_runtime_put(dev);
netdev_dbg(ndev, "mem_base=0x%p irq=%d clock=%d, txb mask:%d\n", netdev_dbg(ndev, "mem_base=0x%p irq=%d clock=%d, txb mask:%d\n",
priv->p.mem_base, ndev->irq, priv->can.clock.freq, priv->p.mem_base, ndev->irq, priv->can.clock.freq,
...@@ -1021,9 +1022,62 @@ static int ctucan_probe(struct platform_device *pdev) ...@@ -1021,9 +1022,62 @@ static int ctucan_probe(struct platform_device *pdev)
err_disableclks: err_disableclks:
pm_runtime_put(priv->dev); pm_runtime_put(priv->dev);
err_pmdisable: err_pmdisable:
pm_runtime_disable(&pdev->dev); pm_runtime_disable(dev);
err_free: err_free:
free_candev(ndev); free_candev(ndev);
return ret;
}
static void ctucan_set_drvdata_platform(struct device *dev,
struct net_device *ndev)
{
struct platform_device *pdev = container_of(dev, struct platform_device, dev);
platform_set_drvdata(pdev, ndev);
}
/**
* ctucan_probe - Platform registration call
* @pdev: Handle to the platform device structure
*
* This function does all the memory allocation and registration for the CAN
* device.
*
* Return: 0 on success and failure value on error
*/
static int ctucan_platform_probe(struct platform_device *pdev)
{
struct resource *res; /* IO mem resources */
struct device *dev = &pdev->dev;
void __iomem *addr;
int ret;
unsigned int ntxbufs;
int irq;
/* Get the virtual base address for the device */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
addr = devm_ioremap_resource(dev, res);
if (IS_ERR(addr)) {
dev_err(dev, "Cannot remap address.\n");
ret = PTR_ERR(addr);
goto err;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "Cannot find interrupt.\n");
ret = irq;
goto err;
}
/*
ret = of_property_read_u32(pdev->dev.of_node, "tx-fifo-depth", &tx_max);
if (ret < 0)
goto err;
*/
ntxbufs = 4;
ret = ctucan_probe_common(dev, addr, irq, ntxbufs, 0,
ctucan_set_drvdata_platform);
err: err:
return ret; return ret;
} }
...@@ -1035,7 +1089,7 @@ err: ...@@ -1035,7 +1089,7 @@ err:
* This function frees all the resources allocated to the device. * This function frees all the resources allocated to the device.
* Return: 0 always * Return: 0 always
*/ */
static int ctucan_remove(struct platform_device *pdev) static int ctucan_platform_remove(struct platform_device *pdev)
{ {
struct net_device *ndev = platform_get_drvdata(pdev); struct net_device *ndev = platform_get_drvdata(pdev);
struct ctucan_priv *priv = netdev_priv(ndev); struct ctucan_priv *priv = netdev_priv(ndev);
...@@ -1059,8 +1113,8 @@ static const struct of_device_id ctucan_of_match[] = { ...@@ -1059,8 +1113,8 @@ static const struct of_device_id ctucan_of_match[] = {
MODULE_DEVICE_TABLE(of, ctucan_of_match); MODULE_DEVICE_TABLE(of, ctucan_of_match);
static struct platform_driver ctucanfd_driver = { static struct platform_driver ctucanfd_driver = {
.probe = ctucan_probe, .probe = ctucan_platform_probe,
.remove = ctucan_remove, .remove = ctucan_platform_remove,
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.pm = &ctucan_dev_pm_ops, .pm = &ctucan_dev_pm_ops,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment