linux/drivers/mfd/mc13xxx-spi.c
<<
>>
Prefs
   1/*
   2 * Copyright 2009-2010 Pengutronix
   3 * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
   4 *
   5 * loosely based on an earlier driver that has
   6 * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
   7 *
   8 * This program is free software; you can redistribute it and/or modify it under
   9 * the terms of the GNU General Public License version 2 as published by the
  10 * Free Software Foundation.
  11 */
  12
  13#include <linux/slab.h>
  14#include <linux/module.h>
  15#include <linux/platform_device.h>
  16#include <linux/mutex.h>
  17#include <linux/interrupt.h>
  18#include <linux/mfd/core.h>
  19#include <linux/mfd/mc13xxx.h>
  20#include <linux/of.h>
  21#include <linux/of_device.h>
  22#include <linux/of_gpio.h>
  23#include <linux/err.h>
  24#include <linux/spi/spi.h>
  25
  26#include "mc13xxx.h"
  27
  28static const struct spi_device_id mc13xxx_device_id[] = {
  29        {
  30                .name = "mc13783",
  31                .driver_data = (kernel_ulong_t)&mc13xxx_variant_mc13783,
  32        }, {
  33                .name = "mc13892",
  34                .driver_data = (kernel_ulong_t)&mc13xxx_variant_mc13892,
  35        }, {
  36                .name = "mc34708",
  37                .driver_data = (kernel_ulong_t)&mc13xxx_variant_mc34708,
  38        }, {
  39                /* sentinel */
  40        }
  41};
  42MODULE_DEVICE_TABLE(spi, mc13xxx_device_id);
  43
  44static const struct of_device_id mc13xxx_dt_ids[] = {
  45        { .compatible = "fsl,mc13783", .data = &mc13xxx_variant_mc13783, },
  46        { .compatible = "fsl,mc13892", .data = &mc13xxx_variant_mc13892, },
  47        { .compatible = "fsl,mc34708", .data = &mc13xxx_variant_mc34708, },
  48        { /* sentinel */ }
  49};
  50MODULE_DEVICE_TABLE(of, mc13xxx_dt_ids);
  51
  52static struct regmap_config mc13xxx_regmap_spi_config = {
  53        .reg_bits = 7,
  54        .pad_bits = 1,
  55        .val_bits = 24,
  56        .write_flag_mask = 0x80,
  57
  58        .max_register = MC13XXX_NUMREGS,
  59
  60        .cache_type = REGCACHE_NONE,
  61        .use_single_rw = 1,
  62};
  63
  64static int mc13xxx_spi_read(void *context, const void *reg, size_t reg_size,
  65                                void *val, size_t val_size)
  66{
  67        unsigned char w[4] = { *((unsigned char *) reg), 0, 0, 0};
  68        unsigned char r[4];
  69        unsigned char *p = val;
  70        struct device *dev = context;
  71        struct spi_device *spi = to_spi_device(dev);
  72        struct spi_transfer t = {
  73                .tx_buf = w,
  74                .rx_buf = r,
  75                .len = 4,
  76        };
  77
  78        struct spi_message m;
  79        int ret;
  80
  81        if (val_size != 3 || reg_size != 1)
  82                return -ENOTSUPP;
  83
  84        spi_message_init(&m);
  85        spi_message_add_tail(&t, &m);
  86        ret = spi_sync(spi, &m);
  87
  88        memcpy(p, &r[1], 3);
  89
  90        return ret;
  91}
  92
  93static int mc13xxx_spi_write(void *context, const void *data, size_t count)
  94{
  95        struct device *dev = context;
  96        struct spi_device *spi = to_spi_device(dev);
  97
  98        if (count != 4)
  99                return -ENOTSUPP;
 100
 101        return spi_write(spi, data, count);
 102}
 103
 104/*
 105 * We cannot use regmap-spi generic bus implementation here.
 106 * The MC13783 chip will get corrupted if CS signal is deasserted
 107 * and on i.Mx31 SoC (the target SoC for MC13783 PMIC) the SPI controller
 108 * has the following errata (DSPhl22960):
 109 * "The CSPI negates SS when the FIFO becomes empty with
 110 * SSCTL= 0. Software cannot guarantee that the FIFO will not
 111 * drain because of higher priority interrupts and the
 112 * non-realtime characteristics of the operating system. As a
 113 * result, the SS will negate before all of the data has been
 114 * transferred to/from the peripheral."
 115 * We workaround this by accessing the SPI controller with a
 116 * single transfert.
 117 */
 118
 119static struct regmap_bus regmap_mc13xxx_bus = {
 120        .write = mc13xxx_spi_write,
 121        .read = mc13xxx_spi_read,
 122};
 123
 124static int mc13xxx_spi_probe(struct spi_device *spi)
 125{
 126        struct mc13xxx *mc13xxx;
 127        struct mc13xxx_platform_data *pdata = dev_get_platdata(&spi->dev);
 128        int ret;
 129
 130        mc13xxx = devm_kzalloc(&spi->dev, sizeof(*mc13xxx), GFP_KERNEL);
 131        if (!mc13xxx)
 132                return -ENOMEM;
 133
 134        dev_set_drvdata(&spi->dev, mc13xxx);
 135        spi->mode = SPI_MODE_0 | SPI_CS_HIGH;
 136
 137        mc13xxx->dev = &spi->dev;
 138        mutex_init(&mc13xxx->lock);
 139
 140        mc13xxx->regmap = devm_regmap_init(&spi->dev, &regmap_mc13xxx_bus,
 141                                           &spi->dev,
 142                                           &mc13xxx_regmap_spi_config);
 143        if (IS_ERR(mc13xxx->regmap)) {
 144                ret = PTR_ERR(mc13xxx->regmap);
 145                dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n",
 146                                ret);
 147                dev_set_drvdata(&spi->dev, NULL);
 1ret;
  49};
1  50  51
spi->dev, mode = "drivvers/mfd/mc13xxx-spi.c#L144" id="L144" cass="line1" name="L52">  52sta1tic s15                      href="+code=of_device_id" class="sref">of_device_id  <">of_device_id <"+code==rs/mfd/mc13xxx-spi.c#L144" id="L144" caass="line" name="L53">  53   1     15      . spi_device > code=mc13xxx" class="sref">"sref">mc13xxx_dt_ids);
spi->dev);
  54   1     1  55   1     15      mc13xxx-> <">of_device_id <"+codecode=dev" class="sreff">data,   56   1     1  57
spi_device_id memcpy("+code=PTR_ERR" class=a> <>(&as="sref">spi_device_id <>(&as="sref">code=mc13xxx" class=f">spi)
  58   1     15drivers/mfd/mc13xxx-spi.c#L119" id="L119" cass="line1" name="L59">  59
mc13xxx->memcpy("+cocode=dev" class="srefss="sref">driver_data = (  60   1     16  61   1     16drivers/mfd/mc13xxx-spi.c#L52" id="L52" cl1ass="line1" name="L62">  62};
1mutex_init(&a>);
onref">code=mc13xxx" class="sref">mc13xxx->pdata = spi->  63
  64sta1tic i16a hrers/mfd/mc13xxx-spi.c#L128" id="L128" cass="line1" name="L65">  65   1     1      ref="+code=mc13xxx_spi_read" class="srefmov>mc13xxx_spi_probe(strucefmov>href="+code=spi_device" class="sref">spi_device *spi)
  66{
<1a hre1="drivers/mfd/mc13xxx-spi.c#L67" id="L67" cl1ass="line1" name="L67">  67   1     16ruct  *mc13xxx;
dev_set_drvdatag&spi->dev,   68   1     16drivers/mfd/mc13xxx-spi.c#L119" id="L119" cass="line1" name="L69">  69   1     1nsigned char *ret" class="sre/a>);
onrcleanu>regmap);
);
onrcleanu>code=mc13xxx" class="sref">mc13xxx->  70   1     17drivers/mfd/mc13xxx-spi.c#L101" id="L101" cass="line1" name="L71">  71   1     17turn   72   1     17"drivers/mfd/mc13xxx-spi.c#L103" id="L103" cass="line1" name="L73">  73   1     17drivers/mfd/mc13xxx-spi.c#L134" id="L134" cass="line1" name="L74">  74   1     17   75   1     1       .compatible i;drivde=dev_get_platdat/a>);
mc13xxx_device_id);
  76   1     17a href="+code=write_flag_masksxxx-sspi_device sxxx-sdrivde=ers/mfd/mc13xxx-spi.c#L67" id="L67" cl1ass="line"  name="L17">  17#incl    17      .spi_device drivde=ding">"mc13892"  78   1     17  79   1     17      compatible of_match"a f">drivde=dev_get_platdat/a>);
mc13xxx_dt_ids);
  80
  81   1     18a href="+code=read" class="srref">mc13xxx_spi_prot mc13xxx_spi_probe(struct   82   1     1       return =read" class="srefmov>mc13xxx_spi_proefmov>hrefde=mc13xxx_spi_read" class="srefmov>mc13xxx_spi_probe(strucefmov>href"rs/mfd/mc13xxx-spi.c#L146" id="L146" cass="line1" name="L83">  83
  84   1     18a hrers/mfd/mc13xxx-spi.c#L128" id="L128" cass="line1" name="L85">  85   1     18     ref="+code=mc13xxx_spi_rea_ref">mutex_init(_ref">code=mc13xxx_spi_read" classef">mutex_init(&a>);
code=+coders/mfd/mc13xxx-spi.c#L125" id="L125" cass="line1" name="L86">  86   1     18"drivers/mfd/mc13xxx-spi.c#L67" id="L67" cl1ass="line1" name="L87">  87
 *  88   1     1a hrefers/mfd/mc13xxx-spi.c#L103" id="L103" cass="line1" name="L89">  89
cal>spi_message_add_ubsysaef">cal>code=mc13xxx" class="sref">"ef">mutex_init(&a>);
codeeers/mfd/mc13xxx-spi.c#L128" id="L128" cass="line1" name="L90">  90   1     19drivers/mfd/mc13xxx-spi.c#L101" id="L101" cass="line1" name="L91">  91}
<1a hre1="drivref="+c+codemc13xxx_spi_rea_rex">mutex_init(_rex">code=mc13xxx_spi_read" classex">mutex_init(d" classex">code=+coders/mfd/mc13xxx-spi.c#L125" id="L125" cass="line1" name="L92">  92
  93sta1tic i19      . *  94{
<1a hre1="drivers/mfd/mc13xxx-spi.c#L103" id="L103" cass="line1" name="L95">  95   1     1truct spi" class="sred
mutex_init(d
code=mc13xxx" class="sref">"ex">mutex_init(d" classex">codeeers/mfd/mc13xxx-spi.c#L128" id="L128" cass="line1" name="L96">  96   1     19drivers/mfd/mc13xxx-spi.c#L137" id="L137" cass="line1" name="L97">  97
(SCRIPTIONmutex_init(ABLE(SCRIPTIONcode=ming">"mc13892"  98   1     1f (PTR_ERR(code=ming">"mc13892"  -Koenigncludu.kle>  -koenig@pengutronix.deode=  19#inclhref19drivespi_device" claABLE ABLE"mc13892" 100
<2 href2"drive


m> s SSorigiedm>LXR pan>uf">y"+coe=ng thext; @l/a>&.no">lx>@l/a>&.no+cod=
m> lx>.l/a>&.no kindly hosl isbyls/mfd/mc1http://www.redpill-l/apro.no">Redpill L/apro A"drive provid-sIof L/aux= hreul a