root/drivers/w1/masters/mxc_w1.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mxc_w1_ds2_reset_bus
  2. mxc_w1_ds2_touch_bit
  3. mxc_w1_probe
  4. mxc_w1_remove

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright 2005-2008 Freescale Semiconductor, Inc. All Rights Reserved.
   4  * Copyright 2008 Luotao Fu, kernel@pengutronix.de
   5  */
   6 
   7 #include <linux/clk.h>
   8 #include <linux/delay.h>
   9 #include <linux/io.h>
  10 #include <linux/jiffies.h>
  11 #include <linux/module.h>
  12 #include <linux/mod_devicetable.h>
  13 #include <linux/platform_device.h>
  14 
  15 #include <linux/w1.h>
  16 
  17 /*
  18  * MXC W1 Register offsets
  19  */
  20 #define MXC_W1_CONTROL          0x00
  21 # define MXC_W1_CONTROL_RDST    BIT(3)
  22 # define MXC_W1_CONTROL_WR(x)   BIT(5 - (x))
  23 # define MXC_W1_CONTROL_PST     BIT(6)
  24 # define MXC_W1_CONTROL_RPP     BIT(7)
  25 #define MXC_W1_TIME_DIVIDER     0x02
  26 #define MXC_W1_RESET            0x04
  27 # define MXC_W1_RESET_RST       BIT(0)
  28 
  29 struct mxc_w1_device {
  30         void __iomem *regs;
  31         struct clk *clk;
  32         struct w1_bus_master bus_master;
  33 };
  34 
  35 /*
  36  * this is the low level routine to
  37  * reset the device on the One Wire interface
  38  * on the hardware
  39  */
  40 static u8 mxc_w1_ds2_reset_bus(void *data)
  41 {
  42         struct mxc_w1_device *dev = data;
  43         unsigned long timeout;
  44 
  45         writeb(MXC_W1_CONTROL_RPP, dev->regs + MXC_W1_CONTROL);
  46 
  47         /* Wait for reset sequence 511+512us, use 1500us for sure */
  48         timeout = jiffies + usecs_to_jiffies(1500);
  49 
  50         udelay(511 + 512);
  51 
  52         do {
  53                 u8 ctrl = readb(dev->regs + MXC_W1_CONTROL);
  54 
  55                 /* PST bit is valid after the RPP bit is self-cleared */
  56                 if (!(ctrl & MXC_W1_CONTROL_RPP))
  57                         return !(ctrl & MXC_W1_CONTROL_PST);
  58         } while (time_is_after_jiffies(timeout));
  59 
  60         return 1;
  61 }
  62 
  63 /*
  64  * this is the low level routine to read/write a bit on the One Wire
  65  * interface on the hardware. It does write 0 if parameter bit is set
  66  * to 0, otherwise a write 1/read.
  67  */
  68 static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit)
  69 {
  70         struct mxc_w1_device *dev = data;
  71         unsigned long timeout;
  72 
  73         writeb(MXC_W1_CONTROL_WR(bit), dev->regs + MXC_W1_CONTROL);
  74 
  75         /* Wait for read/write bit (60us, Max 120us), use 200us for sure */
  76         timeout = jiffies + usecs_to_jiffies(200);
  77 
  78         udelay(60);
  79 
  80         do {
  81                 u8 ctrl = readb(dev->regs + MXC_W1_CONTROL);
  82 
  83                 /* RDST bit is valid after the WR1/RD bit is self-cleared */
  84                 if (!(ctrl & MXC_W1_CONTROL_WR(bit)))
  85                         return !!(ctrl & MXC_W1_CONTROL_RDST);
  86         } while (time_is_after_jiffies(timeout));
  87 
  88         return 0;
  89 }
  90 
  91 static int mxc_w1_probe(struct platform_device *pdev)
  92 {
  93         struct mxc_w1_device *mdev;
  94         unsigned long clkrate;
  95         unsigned int clkdiv;
  96         int err;
  97 
  98         mdev = devm_kzalloc(&pdev->dev, sizeof(struct mxc_w1_device),
  99                             GFP_KERNEL);
 100         if (!mdev)
 101                 return -ENOMEM;
 102 
 103         mdev->clk = devm_clk_get(&pdev->dev, NULL);
 104         if (IS_ERR(mdev->clk))
 105                 return PTR_ERR(mdev->clk);
 106 
 107         err = clk_prepare_enable(mdev->clk);
 108         if (err)
 109                 return err;
 110 
 111         clkrate = clk_get_rate(mdev->clk);
 112         if (clkrate < 10000000)
 113                 dev_warn(&pdev->dev,
 114                          "Low clock frequency causes improper function\n");
 115 
 116         clkdiv = DIV_ROUND_CLOSEST(clkrate, 1000000);
 117         clkrate /= clkdiv;
 118         if ((clkrate < 980000) || (clkrate > 1020000))
 119                 dev_warn(&pdev->dev,
 120                          "Incorrect time base frequency %lu Hz\n", clkrate);
 121 
 122         mdev->regs = devm_platform_ioremap_resource(pdev, 0);
 123         if (IS_ERR(mdev->regs)) {
 124                 err = PTR_ERR(mdev->regs);
 125                 goto out_disable_clk;
 126         }
 127 
 128         /* Software reset 1-Wire module */
 129         writeb(MXC_W1_RESET_RST, mdev->regs + MXC_W1_RESET);
 130         writeb(0, mdev->regs + MXC_W1_RESET);
 131 
 132         writeb(clkdiv - 1, mdev->regs + MXC_W1_TIME_DIVIDER);
 133 
 134         mdev->bus_master.data = mdev;
 135         mdev->bus_master.reset_bus = mxc_w1_ds2_reset_bus;
 136         mdev->bus_master.touch_bit = mxc_w1_ds2_touch_bit;
 137 
 138         platform_set_drvdata(pdev, mdev);
 139 
 140         err = w1_add_master_device(&mdev->bus_master);
 141         if (err)
 142                 goto out_disable_clk;
 143 
 144         return 0;
 145 
 146 out_disable_clk:
 147         clk_disable_unprepare(mdev->clk);
 148         return err;
 149 }
 150 
 151 /*
 152  * disassociate the w1 device from the driver
 153  */
 154 static int mxc_w1_remove(struct platform_device *pdev)
 155 {
 156         struct mxc_w1_device *mdev = platform_get_drvdata(pdev);
 157 
 158         w1_remove_master_device(&mdev->bus_master);
 159 
 160         clk_disable_unprepare(mdev->clk);
 161 
 162         return 0;
 163 }
 164 
 165 static const struct of_device_id mxc_w1_dt_ids[] = {
 166         { .compatible = "fsl,imx21-owire" },
 167         { /* sentinel */ }
 168 };
 169 MODULE_DEVICE_TABLE(of, mxc_w1_dt_ids);
 170 
 171 static struct platform_driver mxc_w1_driver = {
 172         .driver = {
 173                 .name = "mxc_w1",
 174                 .of_match_table = mxc_w1_dt_ids,
 175         },
 176         .probe = mxc_w1_probe,
 177         .remove = mxc_w1_remove,
 178 };
 179 module_platform_driver(mxc_w1_driver);
 180 
 181 MODULE_LICENSE("GPL");
 182 MODULE_AUTHOR("Freescale Semiconductors Inc");
 183 MODULE_DESCRIPTION("Driver for One-Wire on MXC");

/* [<][>][^][v][top][bottom][index][help] */