Blame view

drivers/mfd/bcm590xx.c 3.18 KB
037b60f2c   Matt Porter   mfd: Add bcm590xx...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  /*
   * Broadcom BCM590xx PMU
   *
   * Copyright 2014 Linaro Limited
   * Author: Matt Porter <mporter@linaro.org>
   *
   * This program is free software; you can redistribute it and/or modify it
   * under  the terms of the GNU General  Public License as published by the
   * Free Software Foundation;  either version 2 of the License, or (at your
   * option) any later version.
   */
  
  #include <linux/err.h>
  #include <linux/i2c.h>
  #include <linux/init.h>
  #include <linux/mfd/bcm590xx.h>
  #include <linux/mfd/core.h>
  #include <linux/module.h>
  #include <linux/moduleparam.h>
  #include <linux/of.h>
  #include <linux/of_device.h>
  #include <linux/regmap.h>
  #include <linux/slab.h>
  
  static const struct mfd_cell bcm590xx_devs[] = {
  	{
  		.name = "bcm590xx-vregs",
  	},
  };
9e1e72631   Matt Porter   mfd: bcm590xx: Ad...
30
  static const struct regmap_config bcm590xx_regmap_config_pri = {
037b60f2c   Matt Porter   mfd: Add bcm590xx...
31
32
  	.reg_bits	= 8,
  	.val_bits	= 8,
9e1e72631   Matt Porter   mfd: bcm590xx: Ad...
33
  	.max_register	= BCM590XX_MAX_REGISTER_PRI,
037b60f2c   Matt Porter   mfd: Add bcm590xx...
34
35
  	.cache_type	= REGCACHE_RBTREE,
  };
9e1e72631   Matt Porter   mfd: bcm590xx: Ad...
36
37
38
39
40
41
42
43
  static const struct regmap_config bcm590xx_regmap_config_sec = {
  	.reg_bits	= 8,
  	.val_bits	= 8,
  	.max_register	= BCM590XX_MAX_REGISTER_SEC,
  	.cache_type	= REGCACHE_RBTREE,
  };
  
  static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri,
037b60f2c   Matt Porter   mfd: Add bcm590xx...
44
45
46
47
  			      const struct i2c_device_id *id)
  {
  	struct bcm590xx *bcm590xx;
  	int ret;
9e1e72631   Matt Porter   mfd: bcm590xx: Ad...
48
  	bcm590xx = devm_kzalloc(&i2c_pri->dev, sizeof(*bcm590xx), GFP_KERNEL);
037b60f2c   Matt Porter   mfd: Add bcm590xx...
49
50
  	if (!bcm590xx)
  		return -ENOMEM;
9e1e72631   Matt Porter   mfd: bcm590xx: Ad...
51
52
53
  	i2c_set_clientdata(i2c_pri, bcm590xx);
  	bcm590xx->dev = &i2c_pri->dev;
  	bcm590xx->i2c_pri = i2c_pri;
037b60f2c   Matt Porter   mfd: Add bcm590xx...
54

9e1e72631   Matt Porter   mfd: bcm590xx: Ad...
55
56
57
58
59
60
  	bcm590xx->regmap_pri = devm_regmap_init_i2c(i2c_pri,
  						 &bcm590xx_regmap_config_pri);
  	if (IS_ERR(bcm590xx->regmap_pri)) {
  		ret = PTR_ERR(bcm590xx->regmap_pri);
  		dev_err(&i2c_pri->dev, "primary regmap init failed: %d
  ", ret);
037b60f2c   Matt Porter   mfd: Add bcm590xx...
61
62
  		return ret;
  	}
9e1e72631   Matt Porter   mfd: bcm590xx: Ad...
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  	/* Secondary I2C slave address is the base address with A(2) asserted */
  	bcm590xx->i2c_sec = i2c_new_dummy(i2c_pri->adapter,
  					  i2c_pri->addr | BIT(2));
  	if (IS_ERR_OR_NULL(bcm590xx->i2c_sec)) {
  		dev_err(&i2c_pri->dev, "failed to add secondary I2C device
  ");
  		return -ENODEV;
  	}
  	i2c_set_clientdata(bcm590xx->i2c_sec, bcm590xx);
  
  	bcm590xx->regmap_sec = devm_regmap_init_i2c(bcm590xx->i2c_sec,
  						&bcm590xx_regmap_config_sec);
  	if (IS_ERR(bcm590xx->regmap_sec)) {
  		ret = PTR_ERR(bcm590xx->regmap_sec);
  		dev_err(&bcm590xx->i2c_sec->dev,
  			"secondary regmap init failed: %d
  ", ret);
  		goto err;
  	}
9148f2c01   Laxman Dewangan   mfd: bcm590xx: Us...
82
83
  	ret = devm_mfd_add_devices(&i2c_pri->dev, -1, bcm590xx_devs,
  				   ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL);
9e1e72631   Matt Porter   mfd: bcm590xx: Ad...
84
85
86
87
88
89
90
  	if (ret < 0) {
  		dev_err(&i2c_pri->dev, "failed to add sub-devices: %d
  ", ret);
  		goto err;
  	}
  
  	return 0;
037b60f2c   Matt Porter   mfd: Add bcm590xx...
91

9e1e72631   Matt Porter   mfd: bcm590xx: Ad...
92
93
  err:
  	i2c_unregister_device(bcm590xx->i2c_sec);
037b60f2c   Matt Porter   mfd: Add bcm590xx...
94
95
96
97
98
99
100
  	return ret;
  }
  
  static const struct of_device_id bcm590xx_of_match[] = {
  	{ .compatible = "brcm,bcm59056" },
  	{ }
  };
3827c510b   Axel Lin   mfd: bcm590xx: Fi...
101
  MODULE_DEVICE_TABLE(of, bcm590xx_of_match);
037b60f2c   Matt Porter   mfd: Add bcm590xx...
102
103
104
105
106
107
108
109
110
111
  
  static const struct i2c_device_id bcm590xx_i2c_id[] = {
  	{ "bcm59056" },
  	{ }
  };
  MODULE_DEVICE_TABLE(i2c, bcm590xx_i2c_id);
  
  static struct i2c_driver bcm590xx_i2c_driver = {
  	.driver = {
  		   .name = "bcm590xx",
037b60f2c   Matt Porter   mfd: Add bcm590xx...
112
113
114
115
116
117
118
119
120
121
  		   .of_match_table = of_match_ptr(bcm590xx_of_match),
  	},
  	.probe = bcm590xx_i2c_probe,
  	.id_table = bcm590xx_i2c_id,
  };
  module_i2c_driver(bcm590xx_i2c_driver);
  
  MODULE_AUTHOR("Matt Porter <mporter@linaro.org>");
  MODULE_DESCRIPTION("BCM590xx multi-function driver");
  MODULE_LICENSE("GPL v2");