* Re: [PATCH linux v5 2/2] drivers: hwmon: Support for ASPEED PWM/Fan tach
From: Guenter Roeck @ 2017-04-01 22:45 UTC (permalink / raw)
To: Jaghathiswari Rankappagounder Natarajan,
joel-U3u1mxZcP9KHXe+LvDLADg, jdelvare-IBi9RG/b67k,
linux-hwmon-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
openbmc-uLR06cmDAlY/bJ5BZ2RsiQ, corbet-T1hC0tSOHrs,
linux-doc-u79uwXL29TY76Z2rM5mHXA, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170324181723.29379-3-jaghu-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
On 03/24/2017 11:17 AM, Jaghathiswari Rankappagounder Natarajan wrote:
> The ASPEED AST2400/2500 PWM controller supports 8 PWM output ports.
> The ASPEED AST2400/2500 Fan tach controller supports 16 tachometer
> inputs.
> The device driver matches on the device tree node. The configuration
> values
> are read from the device tree and written to the respective registers.
> The driver provides a sysfs entries through which the user can
> configure the duty-cycle value (ranging from 0 to 100 percent) and read
> the
> fan tach rpm value.
>
Odd line breaks.
> Signed-off-by: Jaghathiswari Rankappagounder Natarajan <jaghu-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
> ---
> v5:
> - Changed the driver to suit the changes in the device tree documentation
>
> v4:
> - Modified this driver to suit the representation in the devicetree
>
> v3:
> - Only sent out device tree documentation; did not send this driver
>
> v2:
> - Used BIT()
> - Used regmap
> - Avoided division when raw data is 0
> - Removed empty lines between declaration
> - Removed macros; Used two attribute groups and used is_visible callback
> - Returned error when properties are undefined
> - Removed .owner field
> - Used PTR_ERR_OR_ZERO
> - Removed explicit of_node_put for child nodes
>
> Documentation/hwmon/aspeed-pwm-tacho | 22 +
> drivers/hwmon/Kconfig | 13 +-
> drivers/hwmon/Makefile | 1 +
> drivers/hwmon/aspeed-pwm-tacho.c | 854 +++++++++++++++++++++++++++++++++++
> 4 files changed, 888 insertions(+), 2 deletions(-)
> create mode 100644 Documentation/hwmon/aspeed-pwm-tacho
> create mode 100644 drivers/hwmon/aspeed-pwm-tacho.c
>
> diff --git a/Documentation/hwmon/aspeed-pwm-tacho b/Documentation/hwmon/aspeed-pwm-tacho
> new file mode 100644
> index 000000000000..0e9ec6d5f900
> --- /dev/null
> +++ b/Documentation/hwmon/aspeed-pwm-tacho
> @@ -0,0 +1,22 @@
> +Kernel driver aspeed-pwm-tacho
> +==============================
> +
> +Supported chips:
> + ASPEED AST2400/2500
> +
> +Authors:
> + <jaghu-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
> +
> +Description:
> +------------
> +This driver implements support for ASPEED AST2400/2500 PWM and Fan Tacho
> +controller. The PWM controller supports upto 8 PWM outputs. The Fan tacho
> +controller supports upto 16 tachometer inputs.
> +
up to
> +The driver provides the following sensor accesses in sysfs:
> +
> +fanX_input ro provide current fan rotation value in RPM as reported
> + by the fan to the device.
> +
> +pwmX rw get or set PWM fan control value. This is an integer
> + value between 0(off) and 255(full speed).
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index 45cef3d2c75c..487110f21827 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -341,6 +341,15 @@ config SENSORS_ASB100
> This driver can also be built as a module. If so, the module
> will be called asb100.
>
> +config SENSORS_ASPEED
> + tristate "ASPEED AST2400/AST2500 PWM and Fan tach driver"
> + help
> + This driver provides support for ASPEED AST2400/AST2500 PWM
> + and Fan Tacho controllers.
> +
> + This driver can also be built as a module. If so, the module
> + will be called aspeed_pwm_tacho.
> +
> config SENSORS_ATXP1
> tristate "Attansic ATXP1 VID controller"
> depends on I2C
> @@ -952,7 +961,7 @@ config SENSORS_LM70
> help
> If you say yes here you get support for the National Semiconductor
> LM70, LM71, LM74 and Texas Instruments TMP121/TMP123 digital tempera-
> - ture sensor chips.
> + true sensor chips.
Unrelated. Please drop. Separate patch would be appreciated, of course.
>
> This driver can also be built as a module. If so, the module
> will be called lm70.
> @@ -1506,7 +1515,7 @@ config SENSORS_ADS7871
>
> config SENSORS_AMC6821
> tristate "Texas Instruments AMC6821"
> - depends on I2C
> + depends on I2C
Unrelated. Please drop.
> help
> If you say yes here you get support for the Texas Instruments
> AMC6821 hardware monitoring chips.
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index aecf4ba17460..83025cc9bb45 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -46,6 +46,7 @@ obj-$(CONFIG_SENSORS_ADT7475) += adt7475.o
> obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o
> obj-$(CONFIG_SENSORS_ARM_SCPI) += scpi-hwmon.o
> obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o
> +obj-$(CONFIG_SENSORS_ASPEED) += aspeed-pwm-tacho.o
> obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
> obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
> obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o
> diff --git a/drivers/hwmon/aspeed-pwm-tacho.c b/drivers/hwmon/aspeed-pwm-tacho.c
> new file mode 100644
> index 000000000000..28888cc34555
> --- /dev/null
> +++ b/drivers/hwmon/aspeed-pwm-tacho.c
> @@ -0,0 +1,854 @@
> +/*
> + * Copyright (c) 2016 Google, Inc
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 or later as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/delay.h>
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/sysfs.h>
> +#include <linux/regmap.h>
> +
> +/* ASPEED PWM & FAN Tach Register Definition */
> +#define ASPEED_PTCR_CTRL 0x00
> +#define ASPEED_PTCR_CLK_CTRL 0x04
> +#define ASPEED_PTCR_DUTY0_CTRL 0x08
> +#define ASPEED_PTCR_DUTY1_CTRL 0x0c
> +#define ASPEED_PTCR_TYPEM_CTRL 0x10
> +#define ASPEED_PTCR_TYPEM_CTRL1 0x14
> +#define ASPEED_PTCR_TYPEN_CTRL 0x18
> +#define ASPEED_PTCR_TYPEN_CTRL1 0x1c
> +#define ASPEED_PTCR_TACH_SOURCE 0x20
> +#define ASPEED_PTCR_TRIGGER 0x28
> +#define ASPEED_PTCR_RESULT 0x2c
> +#define ASPEED_PTCR_INTR_CTRL 0x30
> +#define ASPEED_PTCR_INTR_STS 0x34
> +#define ASPEED_PTCR_TYPEM_LIMIT 0x38
> +#define ASPEED_PTCR_TYPEN_LIMIT 0x3C
> +#define ASPEED_PTCR_CTRL_EXT 0x40
> +#define ASPEED_PTCR_CLK_CTRL_EXT 0x44
> +#define ASPEED_PTCR_DUTY2_CTRL 0x48
> +#define ASPEED_PTCR_DUTY3_CTRL 0x4c
> +#define ASPEED_PTCR_TYPEO_CTRL 0x50
> +#define ASPEED_PTCR_TYPEO_CTRL1 0x54
> +#define ASPEED_PTCR_TACH_SOURCE_EXT 0x60
> +#define ASPEED_PTCR_TYPEO_LIMIT 0x78
> +
> +/* ASPEED_PTCR_CTRL : 0x00 - General Control Register */
> +#define ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART1 15
> +#define ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART2 6
> +#define ASPEED_PTCR_CTRL_SET_PWMD_TYPE_MASK (BIT(7) | BIT(15))
> +
> +#define ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART1 14
> +#define ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART2 5
> +#define ASPEED_PTCR_CTRL_SET_PWMC_TYPE_MASK (BIT(6) | BIT(14))
> +
> +#define ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART1 13
> +#define ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART2 4
> +#define ASPEED_PTCR_CTRL_SET_PWMB_TYPE_MASK (BIT(5) | BIT(13))
> +
> +#define ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART1 12
> +#define ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART2 3
> +#define ASPEED_PTCR_CTRL_SET_PWMA_TYPE_MASK (BIT(4) | BIT(12))
> +
> +#define ASPEED_PTCR_CTRL_FAN_NUM_EN(x) BIT(16 + (x))
> +
> +#define ASPEED_PTCR_CTRL_PWMD_EN BIT(11)
> +#define ASPEED_PTCR_CTRL_PWMC_EN BIT(10)
> +#define ASPEED_PTCR_CTRL_PWMB_EN BIT(9)
> +#define ASPEED_PTCR_CTRL_PWMA_EN BIT(8)
> +
> +#define ASPEED_PTCR_CTRL_CLK_SRC BIT(1)
> +#define ASPEED_PTCR_CTRL_CLK_EN BIT(0)
> +
> +/* ASPEED_PTCR_CLK_CTRL : 0x04 - Clock Control Register */
> +/* TYPE N */
> +#define ASPEED_PTCR_CLK_CTRL_TYPEN_MASK GENMASK(31, 16)
> +#define ASPEED_PTCR_CLK_CTRL_TYPEN_UNIT 24
> +#define ASPEED_PTCR_CLK_CTRL_TYPEN_H 20
> +#define ASPEED_PTCR_CLK_CTRL_TYPEN_L 16
> +/* TYPE M */
> +#define ASPEED_PTCR_CLK_CTRL_TYPEM_MASK GENMASK(15, 0)
> +#define ASPEED_PTCR_CLK_CTRL_TYPEM_UNIT 8
> +#define ASPEED_PTCR_CLK_CTRL_TYPEM_H 4
> +#define ASPEED_PTCR_CLK_CTRL_TYPEM_L 0
> +
> +/*
> + * ASPEED_PTCR_DUTY_CTRL/1/2/3 : 0x08/0x0C/0x48/0x4C - PWM-FAN duty control
> + * 0/1/2/3 register
> + */
> +#define DUTY_CTRL_PWM2_FALL_POINT 24
> +#define DUTY_CTRL_PWM2_RISE_POINT 16
> +#define DUTY_CTRL_PWM2_RISE_FALL_MASK GENMASK(31, 16)
> +#define DUTY_CTRL_PWM1_FALL_POINT 8
> +#define DUTY_CTRL_PWM1_RISE_POINT 0
> +#define DUTY_CTRL_PWM1_RISE_FALL_MASK GENMASK(15, 0)
> +
> +/* ASPEED_PTCR_TYPEM_CTRL : 0x10/0x18/0x50 - Type M/N/O Ctrl 0 Register */
> +#define TYPE_CTRL_FAN_MASK (GENMASK(5, 1) | GENMASK(31, 16))
> +#define TYPE_CTRL_FAN1_MASK GENMASK(31, 0)
> +#define TYPE_CTRL_FAN_PERIOD 16
> +#define TYPE_CTRL_FAN_MODE 4
> +#define TYPE_CTRL_FAN_DIVISION 1
> +#define TYPE_CTRL_FAN_TYPE_EN 1
> +
> +/* ASPEED_PTCR_TACH_SOURCE : 0x20/0x60 - Tach Source Register */
> +/* bit [0,1] at 0x20, bit [2] at 0x60 */
> +#define TACH_PWM_SOURCE_BIT01(x) ((x) * 2)
> +#define TACH_PWM_SOURCE_BIT2(x) ((x) * 2)
> +#define TACH_PWM_SOURCE_MASK_BIT01(x) (0x3 << ((x) * 2))
> +#define TACH_PWM_SOURCE_MASK_BIT2(x) BIT((x) * 2)
> +
> +/* ASPEED_PTCR_RESULT : 0x2c - Result Register */
> +#define RESULT_STATUS_MASK BIT(31)
> +#define RESULT_VALUE_MASK 0xfffff
> +
> +/* ASPEED_PTCR_CTRL_EXT : 0x40 - General Control Extension #1 Register */
> +#define ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART1 15
> +#define ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART2 6
> +#define ASPEED_PTCR_CTRL_SET_PWMH_TYPE_MASK (BIT(7) | BIT(15))
> +
> +#define ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART1 14
> +#define ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART2 5
> +#define ASPEED_PTCR_CTRL_SET_PWMG_TYPE_MASK (BIT(6) | BIT(14))
> +
> +#define ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART1 13
> +#define ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART2 4
> +#define ASPEED_PTCR_CTRL_SET_PWMF_TYPE_MASK (BIT(5) | BIT(13))
> +
> +#define ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART1 12
> +#define ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART2 3
> +#define ASPEED_PTCR_CTRL_SET_PWME_TYPE_MASK (BIT(4) | BIT(12))
> +
> +#define ASPEED_PTCR_CTRL_PWMH_EN BIT(11)
> +#define ASPEED_PTCR_CTRL_PWMG_EN BIT(10)
> +#define ASPEED_PTCR_CTRL_PWMF_EN BIT(9)
> +#define ASPEED_PTCR_CTRL_PWME_EN BIT(8)
> +
> +/* ASPEED_PTCR_CLK_EXT_CTRL : 0x44 - Clock Control Extension #1 Register */
> +/* TYPE O */
> +#define ASPEED_PTCR_CLK_CTRL_TYPEO_MASK GENMASK(15, 0)
> +#define ASPEED_PTCR_CLK_CTRL_TYPEO_UNIT 8
> +#define ASPEED_PTCR_CLK_CTRL_TYPEO_H 4
> +#define ASPEED_PTCR_CLK_CTRL_TYPEO_L 0
> +
> +#define PWM_MAX 255
> +
> +#define M_PWM_DIV_H 0x00
> +#define M_PWM_DIV_L 0x05
> +#define M_PWM_PERIOD 0x5F
> +#define M_TACH_CLK_DIV 0x00
> +#define M_TACH_MODE 0x00
> +#define M_TACH_UNIT 0x1000
> +#define INIT_FAN_CTRL 0xFF
> +
> +struct aspeed_pwm_tacho_regmap {
> + void __iomem *regs;
> +};
> +
Can't you just use the regs pointer directly ? Why a structure with just one
variable in it ?
> +struct aspeed_pwm_tacho_data {
> + struct regmap *regmap;
> + unsigned long clk_freq;
> + bool pwm_present[8];
> + bool fan_tach_present[16];
> + u8 type_pwm_clock_unit[3];
> + u8 type_pwm_clock_division_h[3];
> + u8 type_pwm_clock_division_l[3];
> + u8 type_fan_tach_clock_division[3];
> + u16 type_fan_tach_unit[3];
> + u8 pwm_port_type[8];
> + u8 pwm_port_fan_ctrl[8];
> + u8 fan_tach_ch_source[16];
> + const struct attribute_group *groups[2];
groups must be NULL terminated, so you'll need three groups here since
two are used.
> +};
> +
> +enum type { TYPEM, TYPEN, TYPEO };
> +
> +struct type_params {
> + u32 l_value;
> + u32 h_value;
> + u32 unit_value;
> + u32 clk_ctrl_mask;
> + u32 clk_ctrl_reg;
> + u32 ctrl_reg;
> + u32 ctrl_reg1;
> +};
> +
> +static const struct type_params type_params[] = {
> + [TYPEM] = {
> + .l_value = ASPEED_PTCR_CLK_CTRL_TYPEM_L,
> + .h_value = ASPEED_PTCR_CLK_CTRL_TYPEM_H,
> + .unit_value = ASPEED_PTCR_CLK_CTRL_TYPEM_UNIT,
> + .clk_ctrl_mask = ASPEED_PTCR_CLK_CTRL_TYPEM_MASK,
> + .clk_ctrl_reg = ASPEED_PTCR_CLK_CTRL,
> + .ctrl_reg = ASPEED_PTCR_TYPEM_CTRL,
> + .ctrl_reg1 = ASPEED_PTCR_TYPEM_CTRL1,
> + },
> + [TYPEN] = {
> + .l_value = ASPEED_PTCR_CLK_CTRL_TYPEN_L,
> + .h_value = ASPEED_PTCR_CLK_CTRL_TYPEN_H,
> + .unit_value = ASPEED_PTCR_CLK_CTRL_TYPEN_UNIT,
> + .clk_ctrl_mask = ASPEED_PTCR_CLK_CTRL_TYPEN_MASK,
> + .clk_ctrl_reg = ASPEED_PTCR_CLK_CTRL,
> + .ctrl_reg = ASPEED_PTCR_TYPEN_CTRL,
> + .ctrl_reg1 = ASPEED_PTCR_TYPEN_CTRL1,
> + },
> + [TYPEO] = {
> + .l_value = ASPEED_PTCR_CLK_CTRL_TYPEO_L,
> + .h_value = ASPEED_PTCR_CLK_CTRL_TYPEO_H,
> + .unit_value = ASPEED_PTCR_CLK_CTRL_TYPEO_UNIT,
> + .clk_ctrl_mask = ASPEED_PTCR_CLK_CTRL_TYPEO_MASK,
> + .clk_ctrl_reg = ASPEED_PTCR_CLK_CTRL_EXT,
> + .ctrl_reg = ASPEED_PTCR_TYPEO_CTRL,
> + .ctrl_reg1 = ASPEED_PTCR_TYPEO_CTRL1,
> + }
> +};
> +
> +enum pwm_port { PWMA, PWMB, PWMC, PWMD, PWME, PWMF, PWMG, PWMH };
> +
> +struct pwm_port_params {
> + u32 pwm_en;
> + u32 ctrl_reg;
> + u32 type_part1;
> + u32 type_part2;
> + u32 type_mask;
> + u32 duty_ctrl_rise_point;
> + u32 duty_ctrl_fall_point;
> + u32 duty_ctrl_reg;
> + u32 duty_ctrl_rise_fall_mask;
> +};
> +
> +static const struct pwm_port_params pwm_port_params[] = {
> + [PWMA] = {
> + .pwm_en = ASPEED_PTCR_CTRL_PWMA_EN,
> + .ctrl_reg = ASPEED_PTCR_CTRL,
> + .type_part1 = ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART1,
> + .type_part2 = ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART2,
> + .type_mask = ASPEED_PTCR_CTRL_SET_PWMA_TYPE_MASK,
> + .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT,
> + .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT,
> + .duty_ctrl_reg = ASPEED_PTCR_DUTY0_CTRL,
> + .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK,
> + },
> + [PWMB] = {
> + .pwm_en = ASPEED_PTCR_CTRL_PWMB_EN,
> + .ctrl_reg = ASPEED_PTCR_CTRL,
> + .type_part1 = ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART1,
> + .type_part2 = ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART2,
> + .type_mask = ASPEED_PTCR_CTRL_SET_PWMB_TYPE_MASK,
> + .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT,
> + .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT,
> + .duty_ctrl_reg = ASPEED_PTCR_DUTY0_CTRL,
> + .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK,
> + },
> + [PWMC] = {
> + .pwm_en = ASPEED_PTCR_CTRL_PWMC_EN,
> + .ctrl_reg = ASPEED_PTCR_CTRL,
> + .type_part1 = ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART1,
> + .type_part2 = ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART2,
> + .type_mask = ASPEED_PTCR_CTRL_SET_PWMC_TYPE_MASK,
> + .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT,
> + .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT,
> + .duty_ctrl_reg = ASPEED_PTCR_DUTY1_CTRL,
> + .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK,
> + },
> + [PWMD] = {
> + .pwm_en = ASPEED_PTCR_CTRL_PWMD_EN,
> + .ctrl_reg = ASPEED_PTCR_CTRL,
> + .type_part1 = ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART1,
> + .type_part2 = ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART2,
> + .type_mask = ASPEED_PTCR_CTRL_SET_PWMD_TYPE_MASK,
> + .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT,
> + .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT,
> + .duty_ctrl_reg = ASPEED_PTCR_DUTY1_CTRL,
> + .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK,
> + },
> + [PWME] = {
> + .pwm_en = ASPEED_PTCR_CTRL_PWME_EN,
> + .ctrl_reg = ASPEED_PTCR_CTRL_EXT,
> + .type_part1 = ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART1,
> + .type_part2 = ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART2,
> + .type_mask = ASPEED_PTCR_CTRL_SET_PWME_TYPE_MASK,
> + .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT,
> + .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT,
> + .duty_ctrl_reg = ASPEED_PTCR_DUTY2_CTRL,
> + .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK,
> + },
> + [PWMF] = {
> + .pwm_en = ASPEED_PTCR_CTRL_PWMF_EN,
> + .ctrl_reg = ASPEED_PTCR_CTRL_EXT,
> + .type_part1 = ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART1,
> + .type_part2 = ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART2,
> + .type_mask = ASPEED_PTCR_CTRL_SET_PWMF_TYPE_MASK,
> + .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT,
> + .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT,
> + .duty_ctrl_reg = ASPEED_PTCR_DUTY2_CTRL,
> + .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK,
> + },
> + [PWMG] = {
> + .pwm_en = ASPEED_PTCR_CTRL_PWMG_EN,
> + .ctrl_reg = ASPEED_PTCR_CTRL_EXT,
> + .type_part1 = ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART1,
> + .type_part2 = ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART2,
> + .type_mask = ASPEED_PTCR_CTRL_SET_PWMG_TYPE_MASK,
> + .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT,
> + .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT,
> + .duty_ctrl_reg = ASPEED_PTCR_DUTY3_CTRL,
> + .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK,
> + },
> + [PWMH] = {
> + .pwm_en = ASPEED_PTCR_CTRL_PWMH_EN,
> + .ctrl_reg = ASPEED_PTCR_CTRL_EXT,
> + .type_part1 = ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART1,
> + .type_part2 = ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART2,
> + .type_mask = ASPEED_PTCR_CTRL_SET_PWMH_TYPE_MASK,
> + .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT,
> + .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT,
> + .duty_ctrl_reg = ASPEED_PTCR_DUTY3_CTRL,
> + .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK,
> + }
> +};
> +
> +static int regmap_aspeed_pwm_tacho_reg_write(void *context, unsigned int reg,
> + unsigned int val)
> +{
> + struct aspeed_pwm_tacho_regmap *hregmap = context;
> +
> + writel(val, hregmap->regs + reg);
> + return 0;
> +}
> +
> +static int regmap_aspeed_pwm_tacho_reg_read(void *context, unsigned int reg,
> + unsigned int *val)
> +{
> + struct aspeed_pwm_tacho_regmap *hregmap = context;
> +
> + *val = readl(hregmap->regs + reg);
> + return 0;
> +}
> +
> +static const struct regmap_config aspeed_pwm_tacho_regmap_config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .max_register = ASPEED_PTCR_TYPEO_LIMIT,
> + .reg_write = regmap_aspeed_pwm_tacho_reg_write,
> + .reg_read = regmap_aspeed_pwm_tacho_reg_read,
> + .fast_io = true,
> +};
> +
> +static void aspeed_set_clock_enable(struct regmap *regmap, bool val)
> +{
> + regmap_update_bits(regmap, ASPEED_PTCR_CTRL,
> + ASPEED_PTCR_CTRL_CLK_EN,
> + val ? ASPEED_PTCR_CTRL_CLK_EN : 0);
> +}
> +
> +static void aspeed_set_clock_source(struct regmap *regmap, int val)
> +{
> + regmap_update_bits(regmap, ASPEED_PTCR_CTRL,
> + ASPEED_PTCR_CTRL_CLK_SRC,
> + val ? ASPEED_PTCR_CTRL_CLK_SRC : 0);
> +}
> +
> +static void aspeed_set_pwm_clock_values(struct regmap *regmap, u8 type,
> + u8 div_high, u8 div_low, u8 unit)
> +{
> + u32 reg_value = ((div_high << type_params[type].h_value) |
> + (div_low << type_params[type].l_value) |
> + (unit << type_params[type].unit_value));
> +
> + regmap_update_bits(regmap, type_params[type].clk_ctrl_reg,
> + type_params[type].clk_ctrl_mask, reg_value);
> +}
> +
> +static void aspeed_set_pwm_port_enable(struct regmap *regmap, u8 pwm_port,
> + bool enable)
> +{
> + regmap_update_bits(regmap, pwm_port_params[pwm_port].ctrl_reg,
> + pwm_port_params[pwm_port].pwm_en,
> + enable ? pwm_port_params[pwm_port].pwm_en : 0);
> +}
> +
> +static void aspeed_set_pwm_port_type(struct regmap *regmap,
> + u8 pwm_port, u8 type)
> +{
> + u32 reg_value = (type & 0x1) << pwm_port_params[pwm_port].type_part1;
> +
> + reg_value |= (type & 0x2) << pwm_port_params[pwm_port].type_part2;
> +
> + regmap_update_bits(regmap, pwm_port_params[pwm_port].ctrl_reg,
> + pwm_port_params[pwm_port].type_mask, reg_value);
> +}
> +
> +static void aspeed_set_pwm_port_duty_rising_falling(struct regmap *regmap,
> + u8 pwm_port, u8 rising,
> + u8 falling)
> +{
> + u32 reg_value = (rising <<
> + pwm_port_params[pwm_port].duty_ctrl_rise_point);
> + reg_value |= (falling <<
> + pwm_port_params[pwm_port].duty_ctrl_fall_point);
> +
> + regmap_update_bits(regmap, pwm_port_params[pwm_port].duty_ctrl_reg,
> + pwm_port_params[pwm_port].duty_ctrl_rise_fall_mask,
> + reg_value);
> +}
> +
> +static void aspeed_set_tacho_type_enable(struct regmap *regmap, u8 type,
> + bool enable)
> +{
> + regmap_update_bits(regmap, type_params[type].ctrl_reg,
> + TYPE_CTRL_FAN_TYPE_EN,
> + enable ? TYPE_CTRL_FAN_TYPE_EN : 0);
> +}
> +
> +static void aspeed_set_tacho_type_values(struct regmap *regmap, u8 type,
> + u8 mode, u16 unit, u8 division)
> +{
> + u32 reg_value = ((mode << TYPE_CTRL_FAN_MODE) |
> + (unit << TYPE_CTRL_FAN_PERIOD) |
> + (division << TYPE_CTRL_FAN_DIVISION));
> +
> + regmap_update_bits(regmap, type_params[type].ctrl_reg,
> + TYPE_CTRL_FAN_MASK, reg_value);
> + regmap_update_bits(regmap, type_params[type].ctrl_reg1,
> + TYPE_CTRL_FAN1_MASK, unit << 16);
> +}
> +
> +static void aspeed_set_fan_tach_ch_enable(struct regmap *regmap, u8 fan_tach_ch,
> + bool enable)
> +{
> + regmap_update_bits(regmap, ASPEED_PTCR_CTRL,
> + ASPEED_PTCR_CTRL_FAN_NUM_EN(fan_tach_ch),
> + enable ?
> + ASPEED_PTCR_CTRL_FAN_NUM_EN(fan_tach_ch) : 0);
> +}
> +
> +static void aspeed_set_fan_tach_ch_source(struct regmap *regmap, u8 fan_tach_ch,
> + u8 fan_tach_ch_source)
> +{
> + u32 reg_value1 = ((fan_tach_ch_source & 0x3) <<
> + TACH_PWM_SOURCE_BIT01(fan_tach_ch));
> + u32 reg_value2 = (((fan_tach_ch_source & 0x4) >> 2) <<
> + TACH_PWM_SOURCE_BIT2(fan_tach_ch));
> +
> + regmap_update_bits(regmap, ASPEED_PTCR_TACH_SOURCE,
> + TACH_PWM_SOURCE_MASK_BIT01(fan_tach_ch),
> + reg_value1);
> +
> + regmap_update_bits(regmap, ASPEED_PTCR_TACH_SOURCE_EXT,
> + TACH_PWM_SOURCE_MASK_BIT2(fan_tach_ch),
> + reg_value2);
> +}
> +
> +static void aspeed_set_pwm_port_fan_ctrl(struct aspeed_pwm_tacho_data *priv,
> + u8 index, u8 fan_ctrl)
> +{
> + u16 period, dc_time_on;
> +
> + period = priv->type_pwm_clock_unit[priv->pwm_port_type[index]];
> + period += 1;
> + dc_time_on = (fan_ctrl * period) / PWM_MAX;
> +
> + if (dc_time_on == 0) {
> + aspeed_set_pwm_port_enable(priv->regmap, index, false);
> + } else {
> + if (dc_time_on == period)
> + dc_time_on = 0;
> +
> + aspeed_set_pwm_port_duty_rising_falling(priv->regmap, index, 0,
> + dc_time_on);
> + aspeed_set_pwm_port_enable(priv->regmap, index, true);
> + }
> +}
> +
> +static u32 aspeed_get_fan_tach_ch_measure_period(struct aspeed_pwm_tacho_data
> + *priv, u8 type)
> +{
> + u32 clk;
> + u16 tacho_unit;
> + u8 clk_unit, div_h, div_l, tacho_div;
> +
> + clk = priv->clk_freq;
> + clk_unit = priv->type_pwm_clock_unit[type];
> + div_h = priv->type_pwm_clock_division_h[type];
> + div_h = 0x1 << div_h;
> + div_l = priv->type_pwm_clock_division_l[type];
> + if (div_l == 0)
> + div_l = 1;
> + else
> + div_l = div_l * 2;
> +
> + tacho_unit = priv->type_fan_tach_unit[type];
> + tacho_div = priv->type_fan_tach_clock_division[type];
> +
> + tacho_div = 0x4 << (tacho_div * 2);
> + return clk / (clk_unit * div_h * div_l * tacho_div * tacho_unit);
> +}
> +
> +static u32 aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
> + u8 fan_tach_ch)
> +{
> + u32 raw_data, tach_div, clk_source, timeout = 0, sec, val;
> + u8 fan_tach_ch_source, type;
> +
> + regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0);
> + regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0x1 << fan_tach_ch);
> +
> + fan_tach_ch_source = priv->fan_tach_ch_source[fan_tach_ch];
> + type = priv->pwm_port_type[fan_tach_ch_source];
> +
> + sec = (1000 / aspeed_get_fan_tach_ch_measure_period(priv, type));
> +
> + msleep(sec);
> +
> + regmap_read(priv->regmap, ASPEED_PTCR_RESULT, &val);
> + while (!(val & RESULT_STATUS_MASK)) {
> + timeout++;
> + if (timeout > 1)
> + return 0;
> + msleep(sec);
val never changes.
> + }
> +
> + regmap_read(priv->regmap, ASPEED_PTCR_RESULT, &val);
> + raw_data = val & RESULT_VALUE_MASK;
> + tach_div = priv->type_fan_tach_clock_division[type];
> +
> + tach_div = 0x4 << (tach_div * 2);
> + clk_source = priv->clk_freq;
> +
> + if (raw_data == 0)
> + return 0;
> + else
else is unnecessary after return
> + return (clk_source * 60) / (2 * raw_data * tach_div);
> +}
> +
> +static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
> + int index = sensor_attr->index;
> + int ret;
> + struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev);
> + long fan_ctrl;
> +
> + ret = kstrtol(buf, 10, &fan_ctrl);
> + if (ret != 0)
> + return ret;
> +
> + if (fan_ctrl < 0 || fan_ctrl > PWM_MAX)
> + return -EINVAL;
> +
> + if (priv->pwm_port_fan_ctrl[index] == fan_ctrl)
> + return count;
> +
> + priv->pwm_port_fan_ctrl[index] = fan_ctrl;
> + aspeed_set_pwm_port_fan_ctrl(priv, index, fan_ctrl);
> +
> + return count;
> +}
> +
> +static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
> + char *buf)
> +{
> + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
> + int index = sensor_attr->index;
> + struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev);
> +
> + return sprintf(buf, "%u\n", priv->pwm_port_fan_ctrl[index]);
> +}
> +
> +static ssize_t show_rpm(struct device *dev, struct device_attribute *attr,
> + char *buf)
> +{
> + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
> + int index = sensor_attr->index;
> + u32 rpm;
> + struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev);
> +
> + rpm = aspeed_get_fan_tach_ch_rpm(priv, index);
> +
> + return sprintf(buf, "%u\n", rpm);
> +}
> +
> +static umode_t pwm_is_visible(struct kobject *kobj,
> + struct attribute *a, int index)
> +{
> + struct device *dev = container_of(kobj, struct device, kobj);
> + struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev);
> +
> + if (!priv->pwm_present[index])
> + return 0;
> + return a->mode;
> +}
> +
> +static umode_t fan_dev_is_visible(struct kobject *kobj,
> + struct attribute *a, int index)
> +{
> + struct device *dev = container_of(kobj, struct device, kobj);
> + struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev);
> +
> + if (!priv->fan_tach_present[index])
> + return 0;
> + return a->mode;
> +}
> +
> +static SENSOR_DEVICE_ATTR(pwm0, 0644,
> + show_pwm, set_pwm, 0);
> +static SENSOR_DEVICE_ATTR(pwm1, 0644,
> + show_pwm, set_pwm, 1);
> +static SENSOR_DEVICE_ATTR(pwm2, 0644,
> + show_pwm, set_pwm, 2);
> +static SENSOR_DEVICE_ATTR(pwm3, 0644,
> + show_pwm, set_pwm, 3);
> +static SENSOR_DEVICE_ATTR(pwm4, 0644,
> + show_pwm, set_pwm, 4);
> +static SENSOR_DEVICE_ATTR(pwm5, 0644,
> + show_pwm, set_pwm, 5);
> +static SENSOR_DEVICE_ATTR(pwm6, 0644,
> + show_pwm, set_pwm, 6);
> +static SENSOR_DEVICE_ATTR(pwm7, 0644,
> + show_pwm, set_pwm, 7);
Unnecessary continuation lines.
> +
> +static struct attribute *pwm_dev_attrs[] = {
> + &sensor_dev_attr_pwm0.dev_attr.attr,
> + &sensor_dev_attr_pwm1.dev_attr.attr,
> + &sensor_dev_attr_pwm2.dev_attr.attr,
> + &sensor_dev_attr_pwm3.dev_attr.attr,
> + &sensor_dev_attr_pwm4.dev_attr.attr,
> + &sensor_dev_attr_pwm5.dev_attr.attr,
> + &sensor_dev_attr_pwm6.dev_attr.attr,
> + &sensor_dev_attr_pwm7.dev_attr.attr,
> + NULL,
> +};
> +
> +static const struct attribute_group pwm_dev_group = {
> + .attrs = pwm_dev_attrs,
> + .is_visible = pwm_is_visible,
> +};
> +
> +static SENSOR_DEVICE_ATTR(fan0_input, 0444,
> + show_rpm, NULL, 0);
> +static SENSOR_DEVICE_ATTR(fan1_input, 0444,
> + show_rpm, NULL, 1);
> +static SENSOR_DEVICE_ATTR(fan2_input, 0444,
> + show_rpm, NULL, 2);
> +static SENSOR_DEVICE_ATTR(fan3_input, 0444,
> + show_rpm, NULL, 3);
> +static SENSOR_DEVICE_ATTR(fan4_input, 0444,
> + show_rpm, NULL, 4);
> +static SENSOR_DEVICE_ATTR(fan5_input, 0444,
> + show_rpm, NULL, 5);
> +static SENSOR_DEVICE_ATTR(fan6_input, 0444,
> + show_rpm, NULL, 6);
> +static SENSOR_DEVICE_ATTR(fan7_input, 0444,
> + show_rpm, NULL, 7);
> +static SENSOR_DEVICE_ATTR(fan8_input, 0444,
> + show_rpm, NULL, 8);
> +static SENSOR_DEVICE_ATTR(fan9_input, 0444,
> + show_rpm, NULL, 9);
> +static SENSOR_DEVICE_ATTR(fan10_input, 0444,
> + show_rpm, NULL, 10);
> +static SENSOR_DEVICE_ATTR(fan11_input, 0444,
> + show_rpm, NULL, 11);
> +static SENSOR_DEVICE_ATTR(fan12_input, 0444,
> + show_rpm, NULL, 12);
> +static SENSOR_DEVICE_ATTR(fan13_input, 0444,
> + show_rpm, NULL, 13);
> +static SENSOR_DEVICE_ATTR(fan14_input, 0444,
> + show_rpm, NULL, 14);
> +static SENSOR_DEVICE_ATTR(fan15_input, 0444,
> + show_rpm, NULL, 15);
> +
Unnecessary continuation lines.
> +static struct attribute *fan_dev_attrs[] = {
> + &sensor_dev_attr_fan0_input.dev_attr.attr,
> + &sensor_dev_attr_fan1_input.dev_attr.attr,
> + &sensor_dev_attr_fan2_input.dev_attr.attr,
> + &sensor_dev_attr_fan3_input.dev_attr.attr,
> + &sensor_dev_attr_fan4_input.dev_attr.attr,
> + &sensor_dev_attr_fan5_input.dev_attr.attr,
> + &sensor_dev_attr_fan6_input.dev_attr.attr,
> + &sensor_dev_attr_fan7_input.dev_attr.attr,
> + &sensor_dev_attr_fan8_input.dev_attr.attr,
> + &sensor_dev_attr_fan9_input.dev_attr.attr,
> + &sensor_dev_attr_fan10_input.dev_attr.attr,
> + &sensor_dev_attr_fan11_input.dev_attr.attr,
> + &sensor_dev_attr_fan12_input.dev_attr.attr,
> + &sensor_dev_attr_fan13_input.dev_attr.attr,
> + &sensor_dev_attr_fan14_input.dev_attr.attr,
> + &sensor_dev_attr_fan15_input.dev_attr.attr,
> + NULL
> +};
> +
> +static const struct attribute_group fan_dev_group = {
> + .attrs = fan_dev_attrs,
> + .is_visible = fan_dev_is_visible,
> +};
> +
> +/*
> + * The clock type is type M :
> + * The PWM frequency = 24MHz / (type M clock division L bit *
> + * type M clock division H bit * (type M PWM period bit + 1))
> + */
> +static void aspeed_create_type(struct aspeed_pwm_tacho_data *priv)
> +{
> + priv->type_pwm_clock_division_h[TYPEM] = M_PWM_DIV_H;
> + priv->type_pwm_clock_division_l[TYPEM] = M_PWM_DIV_L;
> + priv->type_pwm_clock_unit[TYPEM] = M_PWM_PERIOD;
> + aspeed_set_pwm_clock_values(priv->regmap, TYPEM, M_PWM_DIV_H,
> + M_PWM_DIV_L, M_PWM_PERIOD);
> + aspeed_set_tacho_type_enable(priv->regmap, TYPEM, true);
> + priv->type_fan_tach_clock_division[TYPEM] = M_TACH_CLK_DIV;
> + priv->type_fan_tach_unit[TYPEM] = M_TACH_UNIT;
> + aspeed_set_tacho_type_values(priv->regmap, TYPEM, M_TACH_MODE,
> + M_TACH_UNIT, M_TACH_CLK_DIV);
> +}
> +
> +static void aspeed_create_pwm_port(struct aspeed_pwm_tacho_data *priv,
> + u8 pwm_port)
> +{
> + aspeed_set_pwm_port_enable(priv->regmap, pwm_port, true);
> + priv->pwm_present[pwm_port] = true;
> +
> + priv->pwm_port_type[pwm_port] = TYPEM;
> + aspeed_set_pwm_port_type(priv->regmap, pwm_port, TYPEM);
> +
> + priv->pwm_port_fan_ctrl[pwm_port] = INIT_FAN_CTRL;
> + aspeed_set_pwm_port_fan_ctrl(priv, pwm_port, INIT_FAN_CTRL);
> +}
> +
> +static void aspeed_create_fan_tach_channel(struct aspeed_pwm_tacho_data *priv,
> + u8 *fan_tach_ch,
> + int count,
> + u8 pwm_source)
> +{
> + u8 val, index;
> +
> + for (val = 0; val < count; val++) {
> + index = fan_tach_ch[val];
> + aspeed_set_fan_tach_ch_enable(priv->regmap, index, true);
> + priv->fan_tach_present[index] = true;
> + priv->fan_tach_ch_source[index] = pwm_source;
> + aspeed_set_fan_tach_ch_source(priv->regmap, index, pwm_source);
> + }
> +}
> +
> +static int aspeed_create_fan(struct device *dev,
> + struct device_node *child,
> + struct aspeed_pwm_tacho_data *priv)
> +{
> + u8 *fan_tach_ch;
> + u32 pwm_port;
> + int ret, count;
> +
> + ret = of_property_read_u32(child, "reg", &pwm_port);
> + if (ret)
> + return ret;
> + aspeed_create_pwm_port(priv, (u8)pwm_port);
> +
> + count = of_property_count_u8_elems(child, "aspeed-fan-tach-ch");
> + if (count < 1)
> + return -EINVAL;
> + fan_tach_ch = devm_kzalloc(dev, sizeof(*fan_tach_ch) * count,
> + GFP_KERNEL);
> + if (!fan_tach_ch)
> + return -ENOMEM;
> + ret = of_property_read_u8_array(child, "aspeed-fan-tach-ch",
> + fan_tach_ch, count);
> + if (ret)
> + return ret;
> + aspeed_create_fan_tach_channel(priv, fan_tach_ch, count, pwm_port);
> +
> + return 0;
> +}
> +
> +static int aspeed_pwm_tacho_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *np, *child;
> + struct aspeed_pwm_tacho_data *priv;
> + struct aspeed_pwm_tacho_regmap *hregmap;
> + struct resource *res;
> + struct device *hwmon;
> + struct clk *clk;
> + int ret;
> +
> + np = dev->of_node;
> +
> + hregmap = devm_kzalloc(dev, sizeof(*hregmap), GFP_KERNEL);
> + if (!hregmap)
> + return -ENOMEM;
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res)
> + return -ENOENT;
> + hregmap->regs = devm_ioremap_resource(dev, res);
> + if (IS_ERR(hregmap->regs))
> + return PTR_ERR(hregmap->regs);
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> + priv->regmap = devm_regmap_init(dev, NULL, hregmap,
> + &aspeed_pwm_tacho_regmap_config);
> + if (IS_ERR(priv->regmap))
> + return PTR_ERR(priv->regmap);
> + regmap_write(priv->regmap, ASPEED_PTCR_TACH_SOURCE, 0);
> + regmap_write(priv->regmap, ASPEED_PTCR_TACH_SOURCE_EXT, 0);
> +
> + clk = devm_clk_get(dev, NULL);
> + if (IS_ERR(clk))
> + return -ENODEV;
> + priv->clk_freq = clk_get_rate(clk);
> + aspeed_set_clock_enable(priv->regmap, true);
> + aspeed_set_clock_source(priv->regmap, 0);
> +
> + aspeed_create_type(priv);
> +
> + for_each_child_of_node(np, child) {
> + ret = aspeed_create_fan(dev, child, priv);
> + of_node_put(child);
> + if (ret)
> + return ret;
> + }
> + of_node_put(np);
> +
> + priv->groups[0] = &pwm_dev_group;
> + priv->groups[1] = &fan_dev_group;
> + hwmon = devm_hwmon_device_register_with_groups(dev,
> + "aspeed_pwm_tacho",
> + priv, priv->groups);
> +
> + return PTR_ERR_OR_ZERO(hwmon);
> +}
> +
> +static const struct of_device_id of_pwm_tacho_match_table[] = {
> + { .compatible = "aspeed,ast2400-pwm-tacho", },
> + { .compatible = "aspeed,ast2500-pwm-tacho", },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, of_pwm_tacho_match_table);
> +
> +static struct platform_driver aspeed_pwm_tacho_driver = {
> + .probe = aspeed_pwm_tacho_probe,
> + .driver = {
> + .name = "aspeed_pwm_tacho",
> + .of_match_table = of_pwm_tacho_match_table,
> + },
> +};
> +
> +module_platform_driver(aspeed_pwm_tacho_driver);
> +
> +MODULE_AUTHOR("Jaghathiswari Rankappagounder Natarajan <jaghu-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>");
> +MODULE_DESCRIPTION("ASPEED PWM and Fan Tacho device driver");
> +MODULE_LICENSE("GPL");
> --
> 2.12.1.578.ge9c3154ca4-goog
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] Make EN2 pin optional in the TRF7970A driver
From: Samuel Ortiz @ 2017-04-01 22:35 UTC (permalink / raw)
To: Heiko Schocher
Cc: netdev, devicetree, linux-wireless, linux-kernel, Rob Herring,
Mark Rutland
In-Reply-To: <1486444924-18444-1-git-send-email-hs@denx.de>
Hi Heiko,
On Tue, Feb 07, 2017 at 06:22:04AM +0100, Heiko Schocher wrote:
> From: Guan Ben <ben.guan@cn.bosch.com>
>
> Make the EN2 pin optional. This is useful for boards,
> which have this pin fix wired, for example to ground.
>
> Signed-off-by: Guan Ben <ben.guan@cn.bosch.com>
> Signed-off-by: Mark Jonas <mark.jonas@de.bosch.com>
> Signed-off-by: Heiko Schocher <hs@denx.de>
>
> ---
>
> .../devicetree/bindings/net/nfc/trf7970a.txt | 4 ++--
> drivers/nfc/trf7970a.c | 26 ++++++++++++----------
> 2 files changed, 16 insertions(+), 14 deletions(-)
Applied to nfc-next, thanks.
Cheers,
Samuel.
^ permalink raw reply
* Re: [PATCH V4 1/2] dt-bindings: thermal: add support for Broadcom's Northstar thermal
From: Rafał Miłecki @ 2017-04-01 21:50 UTC (permalink / raw)
To: Eduardo Valentin, Florian Fainelli, Jon Mason
Cc: Zhang Rui, Rob Herring, Mark Rutland, Stephen Warren, Lee Jones,
Eric Anholt, Ray Jui, Scott Branden,
bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w,
linux-pm-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-rpi-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Rafał Miłecki
In-Reply-To: <20170401195136.GD28514-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
On 04/01/2017 09:51 PM, Eduardo Valentin wrote:
> On Fri, Mar 31, 2017 at 10:11:23PM +0200, Rafał Miłecki wrote:
>> From: Rafał Miłecki <rafal-g1n6cQUeyibVItvQsEIGlw@public.gmane.org>
>>
>> This commit documents binding for thermal used in Northstar family SoCs.
>>
>> Signed-off-by: Rafał Miłecki <rafal-g1n6cQUeyibVItvQsEIGlw@public.gmane.org>
>> ---
>> V3: Add thermal-zones to the example
>> Rob: Because of this update, I didn't include Acked-by I got for V2
>> ---
>> .../devicetree/bindings/thermal/brcm,ns-thermal | 26 ++++++++++++++++++++++
>> 1 file changed, 26 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/thermal/brcm,ns-thermal
>>
>> diff --git a/Documentation/devicetree/bindings/thermal/brcm,ns-thermal b/Documentation/devicetree/bindings/thermal/brcm,ns-thermal
>> new file mode 100644
>> index 000000000000..c561c7349f17
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/thermal/brcm,ns-thermal
>> @@ -0,0 +1,26 @@
>> +* Broadcom Northstar Thermal
>> +
>> +This binding describes thermal sensor that is part of Northstar's DMU (Device
>> +Management Unit).
>> +
>> +Required properties:
>> +- compatible : Must be "brcm,ns-thermal"
>> +- reg : iomem address range of PVTMON registers
>> +- #thermal-sensor-cells : Should be <0>
>> +
>> +Example:
>> +
>> +thermal: thermal@1800c2c0 {
>> + compatible = "brcm,ns-thermal";
>> + reg = <0x1800c2c0 0x10>;
>> + #thermal-sensor-cells = <0>;
>> +};
>> +
>> +thermal-zones {
>> + cpu_thermal: cpu-thermal {
>> + polling-delay-passive = <0>;
>> + polling-delay = <1000>;
>> + coefficients = <(-556) 418000>;
>> + thermal-sensors = <&thermal>;
>
> You need to define trips and cooling devices here. Otherwise, makes
> little sense to have this device in thermal subsystem. Here is an
> example of minimal set:
> https://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git/commit/?h=linus&id=1e2ac9821de6a85d3e8358f238436708d1d46869
>
> The above has no passive action. It is just gonna shutdown the system if
> temperature crosses a threshold.
>
> But, a typical cooling device would be CPU frequency throttling. Do you have
> that up and running in your routers?
I don't have CPU freq throttling, so shutdown will be the only solution for
critical temp right now.
I know I should have at least a trip for critical temperature, but the problem
is I don't know what value to use. There isn't any info about this in public
datasheets. Broadcom's SDK doesn't mention it. Vendors share only the max
environment temp, not the max CPU temp.
So for now I only meant to provide user space access to reading current CPU
temperature. I could do some stress tests and ask other users to do it as well.
Or maybe I could just put in Documentation some round value that makes more or
less sense and then work on a proper content of real DTS files?
Unless we can get some hint from Broadcom people. Jon? Florian? Anyone?
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH V4 2/2] thermal: broadcom: add Northstar thermal driver
From: Rafał Miłecki @ 2017-04-01 21:41 UTC (permalink / raw)
To: Eduardo Valentin, Rafał Miłecki
Cc: Mark Rutland, devicetree, Florian Fainelli, Scott Branden,
Stephen Warren, Ray Jui, linux-pm, Lee Jones, Jon Mason,
Eric Anholt, Rob Herring, bcm-kernel-feedback-list,
linux-rpi-kernel, Zhang Rui, linux-arm-kernel
In-Reply-To: <20170401195443.GE28514@localhost.localdomain>
On 04/01/2017 09:54 PM, Eduardo Valentin wrote:
> On Fri, Mar 31, 2017 at 10:11:24PM +0200, Rafał Miłecki wrote:
>> From: Rafał Miłecki <rafal@milecki.pl>
>>
>> Northstar is a SoC family commonly used in home routers. This commit
>> adds a driver for checking CPU temperature. As Northstar Plus seems to
>> also have this IP block this new symbol gets ARCH_BCM_IPROC dependency.
>>
>> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
>> Signed-off-by: Jon Mason <jon.mason@broadcom.com>
>> ---
>
> This driver looks fine from what concerns the of thermal usage.
> I had only one request on the DT bindings example. I believe better to
> get the example fixed so bad DTs does not get copied.
Thanks! I'll comment on this in a reply to patch 1/2.
>> V2: Make it iProc specific as NSP can also use this driver
>> Select proper symbols in config ARCH_BCM_IPROC
>> Define PVTMON register bits
>> Update code selecting temperature monitor mode
>> Thank you Jon!
>> V3: More details in help message for BCM_NS_THERMAL
>> Use slope & offset
>> Drop arch code change (I'll be submitted using a proper tree)
>> Thank you Eduardo!
>> V4: Comment operations on PVTMON_CONTROL0 register
>> ---
>> drivers/thermal/Kconfig | 5 ++
>> drivers/thermal/Makefile | 1 +
>> drivers/thermal/broadcom/Kconfig | 8 +++
>> drivers/thermal/broadcom/Makefile | 1 +
>> drivers/thermal/broadcom/ns-thermal.c | 105 ++++++++++++++++++++++++++++++++++
>
> Also, I have just merged a BRCM driver. Does it make sense to move it
> here too?
>
> It does not need to be a blocking request for this driver though.
Yes, I plan to send a patch for that after getting this one accepted.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH V4 2/2] thermal: broadcom: add Northstar thermal driver
From: Florian Fainelli @ 2017-04-01 20:20 UTC (permalink / raw)
To: Eduardo Valentin, Rafał Miłecki
Cc: Zhang Rui, Rob Herring, Mark Rutland, Stephen Warren, Lee Jones,
Eric Anholt, Ray Jui, Scott Branden, bcm-kernel-feedback-list,
linux-pm, devicetree, linux-rpi-kernel, linux-arm-kernel,
Rafał Miłecki, Jon Mason
In-Reply-To: <20170401195443.GE28514@localhost.localdomain>
On April 1, 2017 12:54:45 PM PDT, Eduardo Valentin <edubezval@gmail.com> wrote:
>Also, I have just merged a BRCM driver. Does it make sense to move it
>here too?
I think it does make sense to have all Broadcom SoCs thermal drivers under a broadcom/ directory. As a matter of fact, I will be submitting another one (for brcmstb SoCs) shortly.
Hi Eduardo,
--
Florian
^ permalink raw reply
* Re: [PATCH V7 6/7] thermal: da9062/61: Thermal junction temperature monitoring driver
From: Eduardo Valentin @ 2017-04-01 19:59 UTC (permalink / raw)
To: Steve Twiss
Cc: LINUX-KERNEL, LINUX-PM, Zhang Rui, DEVICETREE, Dmitry Torokhov,
Guenter Roeck, LINUX-INPUT, LINUX-WATCHDOG, Lee Jones,
Liam Girdwood, Lukasz Luba, Mark Brown, Mark Rutland, Rob Herring,
Support Opensource, Wim Van Sebroeck
In-Reply-To: <2c1ee249b6746ae3914041a4fc106c89a561f7de.1490712213.git.stwiss.opensource@diasemi.com>
Hello,
On Tue, Mar 28, 2017 at 03:43:33PM +0100, Steve Twiss wrote:
> From: Steve Twiss <stwiss.opensource@diasemi.com>
>
> Add junction temperature monitoring supervisor device driver, compatible
> with the DA9062 and DA9061 PMICs. A MODULE_DEVICE_TABLE() macro is added.
>
> If the PMIC's internal junction temperature rises above T_WARN (125 degC)
> an interrupt is issued. This T_WARN level is defined as the
> THERMAL_TRIP_HOT trip-wire inside the device driver.
>
> The thermal triggering mechanism is interrupt based and happens when the
> temperature rises above a given threshold level. The component cannot
> return an exact temperature, it only has knowledge if the temperature is
> above or below a given threshold value. A status bit must be polled to
> detect when the temperature falls below that threshold level again. A
> kernel work queue is configured to repeatedly poll and detect when the
> temperature falls below this trip-wire, between 1 and 10 second intervals
> (defaulting at 3 seconds).
>
> This scheme is provided as an example. It would be expected that any
> final implementation will also include a notify() function and any of these
> settings could be altered to match the application where appropriate.
>
> When over-temperature is reached, the interrupt from the DA9061/2 will be
> repeatedly triggered. The IRQ is therefore disabled when the first
> over-temperature event happens and the status bit is polled using a
> work-queue until it becomes false.
>
> This strategy is designed to allow the periodic transmission of uevents
> (HOT trip point) as the first level of temperature supervision method. It
> is intended for non-invasive temperature control, where the necessary
> measures for cooling the system down are left to the host software. Once
> the temperature falls again, the IRQ is re-enabled so a new critical
> over-temperature event can be detected.
>
> Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
> Signed-off-by: Steve Twiss <stwiss.opensource@diasemi.com>
I have had a look on the history of this driver on its previous
versions, and I do not think I have any other point to request on it.
Obviously, I still need to state that I do not like its oddness as it is
not really benefiting much of the thermal control implemented on the
thermal subsystem.
What is the plan for this series? Am I expected to get this driver
through thermal tree ? Or is this series going into a one shot?
If option 1 is the expected, would the driver need to get its
mfd parent merged first?
>
> ---
> This patch applies against linux-next and v4.11-rc3
>
> v6 -> v7
> - NO CODE CHANGE
> - Compile tested ARCH=x86_64
>
> v5 -> v6
> - Patch renamed from [PATCH V5 7/8] to [PATCH V6 6/7]
> - Rebased from v4.9 to v4.11-rc3
> - Modify Copyright to match Dialog latest legal statement
> - Various checkpatch warnings (from --strict) have been fixed
> - Added COMPILE_TEST to Kconfig
>
> v4 -> v5
> - Rebased from v4.8 to v4.9
> - Updates from comments by Eduardo Valentin
> - Replace vendor defined dlg,tjunc-temp-polling-period-ms with standard
> thermal core polling-delay-passive as part of the device tree
> initialisation
> - Change to the commit message content and device driver source code to
> include an explanation of the repeated uevent strategy for monitoring
> over-temperature
> - Rename warning threshold name from TEMP_WARN to T_WARN to match the
> latest datasheet naming convention
> - Added reviewed-by Lukasz Luba to commit message
>
> v3 -> v4
> - Patch renamed from [PATCH V3 8/9] to [PATCH V4 7/8]
> - Reordering of cancel_delayed_work_sync() in remove function
> - dev_warn() message for out-of-range polling period requests
> - Explanatory comment for expected values defined for
> DEFAULT_POLLING_MS_PERIOD, MAX_POLLING_MS_PERIOD and
> MIN_POLLING_MS_PERIOD
>
> v2 -> v3
> - Patch renamed from [PATCH V2 09/10] to [PATCH V3 8/9]
> - Addition of MODULE_DEVICE_TABLE macro to allow modinfo additions
>
> v1 -> v2
> - Patch renamed from [PATCH V1 05/10] to [PATCH V2 09/10] -- these
> changes were made to fix checkpatch warnings caused by the patch
> set dependency order
> - List the header files in alphabetical order
> - Remove "GPL v2" and replace with MODULE_LICENSE("GPL") to match the
> copyright "GNU Public License v2 or later" option in the header
> comment for this file. See the allowed identifiers in the file
> include/linux/module.h +170
> - Remove notify function "da9062_thermal_notify" function.
> - MODULE_AUTHOR() macros removes Company Name and just gives Name in
> accordance with include/linux/module.h +200
> - Remove the compatible "dlg,da9061-thermal" option in the of_device_id
> struct table. This patch now assumes the use of a DA9062 fallback
> compatible string in the DTS when using the DA9061 thermal component
> of the DA9061 device.
> - Re-ordered some assignments earlier in the probe() for thermal->hw,
> thermal->polling_period, thermal->mode, thermal->dev
> - Added further information in the patch description to explain the use
> of the device driver's built-in work-queue.
>
> Regards,
> Steve Twiss, Dialog Semiconductor
>
>
> drivers/thermal/Kconfig | 10 ++
> drivers/thermal/Makefile | 1 +
> drivers/thermal/da9062-thermal.c | 315 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 326 insertions(+)
> create mode 100644 drivers/thermal/da9062-thermal.c
>
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 776b3439..a784b02 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -303,6 +303,16 @@ config DB8500_CPUFREQ_COOLING
> bound cpufreq cooling device turns active to set CPU frequency low to
> cool down the CPU.
>
> +config DA9062_THERMAL
> + tristate "DA9062/DA9061 Dialog Semiconductor thermal driver"
> + depends on MFD_DA9062 || COMPILE_TEST
> + depends on OF
> + help
> + Enable this for the Dialog Semiconductor thermal sensor driver.
> + This will report PMIC junction over-temperature for one thermal trip
> + zone.
> + Compatible with the DA9062 and DA9061 PMICs.
> +
> config INTEL_POWERCLAMP
> tristate "Intel PowerClamp idle injection driver"
> depends on THERMAL
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index 7adae20..297849e 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -42,6 +42,7 @@ obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
> obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o
> obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o
> obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o
> +obj-$(CONFIG_DA9062_THERMAL) += da9062-thermal.o
> obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
> obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
> obj-$(CONFIG_INTEL_SOC_DTS_IOSF_CORE) += intel_soc_dts_iosf.o
> diff --git a/drivers/thermal/da9062-thermal.c b/drivers/thermal/da9062-thermal.c
> new file mode 100644
> index 0000000..dd8dd94
> --- /dev/null
> +++ b/drivers/thermal/da9062-thermal.c
> @@ -0,0 +1,315 @@
> +/*
> + * Thermal device driver for DA9062 and DA9061
> + * Copyright (C) 2017 Dialog Semiconductor
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +/* When over-temperature is reached, an interrupt from the device will be
> + * triggered. Following this event the interrupt will be disabled and
> + * periodic transmission of uevents (HOT trip point) should define the
> + * first level of temperature supervision. It is expected that any final
> + * implementation of the thermal driver will include a .notify() function
> + * to implement these uevents to userspace.
> + *
> + * These uevents are intended to indicate non-invasive temperature control
> + * of the system, where the necessary measures for cooling are the
> + * responsibility of the host software. Once the temperature falls again,
> + * the IRQ is re-enabled so the start of a new over-temperature event can
> + * be detected without constant software monitoring.
> + */
> +
> +#include <linux/errno.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/thermal.h>
> +#include <linux/workqueue.h>
> +
> +#include <linux/mfd/da9062/core.h>
> +#include <linux/mfd/da9062/registers.h>
> +
> +/* Minimum, maximum and default polling millisecond periods are provided
> + * here as an example. It is expected that any final implementation to also
> + * include a modification of these settings to match the required
> + * application.
> + */
> +#define DA9062_DEFAULT_POLLING_MS_PERIOD 3000
> +#define DA9062_MAX_POLLING_MS_PERIOD 10000
> +#define DA9062_MIN_POLLING_MS_PERIOD 1000
> +
> +#define DA9062_MILLI_CELSIUS(t) ((t) * 1000)
> +
> +struct da9062_thermal_config {
> + const char *name;
> +};
> +
> +struct da9062_thermal {
> + struct da9062 *hw;
> + struct delayed_work work;
> + struct thermal_zone_device *zone;
> + enum thermal_device_mode mode;
> + struct mutex lock; /* protection for da9062_thermal temperature */
> + int temperature;
> + int irq;
> + const struct da9062_thermal_config *config;
> + struct device *dev;
> +};
> +
> +static void da9062_thermal_poll_on(struct work_struct *work)
> +{
> + struct da9062_thermal *thermal = container_of(work,
> + struct da9062_thermal,
> + work.work);
> + unsigned long delay;
> + unsigned int val;
> + int ret;
> +
> + /* clear E_TEMP */
> + ret = regmap_write(thermal->hw->regmap,
> + DA9062AA_EVENT_B,
> + DA9062AA_E_TEMP_MASK);
> + if (ret < 0) {
> + dev_err(thermal->dev,
> + "Cannot clear the TJUNC temperature status\n");
> + goto err_enable_irq;
> + }
> +
> + /* Now read E_TEMP again: it is acting like a status bit.
> + * If over-temperature, then this status will be true.
> + * If not over-temperature, this status will be false.
> + */
> + ret = regmap_read(thermal->hw->regmap,
> + DA9062AA_EVENT_B,
> + &val);
> + if (ret < 0) {
> + dev_err(thermal->dev,
> + "Cannot check the TJUNC temperature status\n");
> + goto err_enable_irq;
> + }
> +
> + if (val & DA9062AA_E_TEMP_MASK) {
> + mutex_lock(&thermal->lock);
> + thermal->temperature = DA9062_MILLI_CELSIUS(125);
> + mutex_unlock(&thermal->lock);
> + thermal_zone_device_update(thermal->zone,
> + THERMAL_EVENT_UNSPECIFIED);
> +
> + delay = msecs_to_jiffies(thermal->zone->passive_delay);
> + schedule_delayed_work(&thermal->work, delay);
> + return;
> + }
> +
> + mutex_lock(&thermal->lock);
> + thermal->temperature = DA9062_MILLI_CELSIUS(0);
> + mutex_unlock(&thermal->lock);
> + thermal_zone_device_update(thermal->zone,
> + THERMAL_EVENT_UNSPECIFIED);
> +
> +err_enable_irq:
> + enable_irq(thermal->irq);
> +}
> +
> +static irqreturn_t da9062_thermal_irq_handler(int irq, void *data)
> +{
> + struct da9062_thermal *thermal = data;
> +
> + disable_irq_nosync(thermal->irq);
> + schedule_delayed_work(&thermal->work, 0);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int da9062_thermal_get_mode(struct thermal_zone_device *z,
> + enum thermal_device_mode *mode)
> +{
> + struct da9062_thermal *thermal = z->devdata;
> + *mode = thermal->mode;
> + return 0;
> +}
> +
> +static int da9062_thermal_get_trip_type(struct thermal_zone_device *z,
> + int trip,
> + enum thermal_trip_type *type)
> +{
> + struct da9062_thermal *thermal = z->devdata;
> +
> + switch (trip) {
> + case 0:
> + *type = THERMAL_TRIP_HOT;
> + break;
> + default:
> + dev_err(thermal->dev,
> + "Driver does not support more than 1 trip-wire\n");
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int da9062_thermal_get_trip_temp(struct thermal_zone_device *z,
> + int trip,
> + int *temp)
> +{
> + struct da9062_thermal *thermal = z->devdata;
> +
> + switch (trip) {
> + case 0:
> + *temp = DA9062_MILLI_CELSIUS(125);
> + break;
> + default:
> + dev_err(thermal->dev,
> + "Driver does not support more than 1 trip-wire\n");
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int da9062_thermal_get_temp(struct thermal_zone_device *z,
> + int *temp)
> +{
> + struct da9062_thermal *thermal = z->devdata;
> +
> + mutex_lock(&thermal->lock);
> + *temp = thermal->temperature;
> + mutex_unlock(&thermal->lock);
> +
> + return 0;
> +}
> +
> +static struct thermal_zone_device_ops da9062_thermal_ops = {
> + .get_temp = da9062_thermal_get_temp,
> + .get_mode = da9062_thermal_get_mode,
> + .get_trip_type = da9062_thermal_get_trip_type,
> + .get_trip_temp = da9062_thermal_get_trip_temp,
> +};
> +
> +static const struct da9062_thermal_config da9062_config = {
> + .name = "da9062-thermal",
> +};
> +
> +static const struct of_device_id da9062_compatible_reg_id_table[] = {
> + { .compatible = "dlg,da9062-thermal", .data = &da9062_config },
> + { },
> +};
> +
> +MODULE_DEVICE_TABLE(of, da9062_compatible_reg_id_table);
> +
> +static int da9062_thermal_probe(struct platform_device *pdev)
> +{
> + struct da9062 *chip = dev_get_drvdata(pdev->dev.parent);
> + struct da9062_thermal *thermal;
> + unsigned int pp_tmp = DA9062_DEFAULT_POLLING_MS_PERIOD;
> + const struct of_device_id *match;
> + int ret = 0;
> +
> + match = of_match_node(da9062_compatible_reg_id_table,
> + pdev->dev.of_node);
> + if (!match)
> + return -ENXIO;
> +
> + if (pdev->dev.of_node) {
> + if (!of_property_read_u32(pdev->dev.of_node,
> + "polling-delay-passive",
> + &pp_tmp)) {
> + if (pp_tmp < DA9062_MIN_POLLING_MS_PERIOD ||
> + pp_tmp > DA9062_MAX_POLLING_MS_PERIOD) {
> + dev_warn(&pdev->dev,
> + "Out-of-range polling period %d ms\n",
> + pp_tmp);
> + pp_tmp = DA9062_DEFAULT_POLLING_MS_PERIOD;
> + }
> + }
> + }
> +
> + thermal = devm_kzalloc(&pdev->dev, sizeof(struct da9062_thermal),
> + GFP_KERNEL);
> + if (!thermal) {
> + ret = -ENOMEM;
> + goto err;
> + }
> +
> + thermal->config = match->data;
> + thermal->hw = chip;
> + thermal->mode = THERMAL_DEVICE_ENABLED;
> + thermal->dev = &pdev->dev;
> +
> + INIT_DELAYED_WORK(&thermal->work, da9062_thermal_poll_on);
> + mutex_init(&thermal->lock);
> +
> + thermal->zone = thermal_zone_device_register(thermal->config->name,
> + 1, 0, thermal,
> + &da9062_thermal_ops, NULL, pp_tmp,
> + 0);
> + if (IS_ERR(thermal->zone)) {
> + dev_err(&pdev->dev, "Cannot register thermal zone device\n");
> + ret = PTR_ERR(thermal->zone);
> + goto err;
> + }
> +
> + dev_dbg(&pdev->dev,
> + "TJUNC temperature polling period set at %d ms\n",
> + thermal->zone->passive_delay);
> +
> + ret = platform_get_irq_byname(pdev, "THERMAL");
> + if (ret < 0) {
> + dev_err(&pdev->dev, "Failed to get platform IRQ.\n");
> + goto err_zone;
> + }
> + thermal->irq = ret;
> +
> + ret = request_threaded_irq(thermal->irq, NULL,
> + da9062_thermal_irq_handler,
> + IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> + "THERMAL", thermal);
> + if (ret) {
> + dev_err(&pdev->dev,
> + "Failed to request thermal device IRQ.\n");
> + goto err_zone;
> + }
> +
> + platform_set_drvdata(pdev, thermal);
> + return 0;
> +
> +err_zone:
> + thermal_zone_device_unregister(thermal->zone);
> +err:
> + return ret;
> +}
> +
> +static int da9062_thermal_remove(struct platform_device *pdev)
> +{
> + struct da9062_thermal *thermal = platform_get_drvdata(pdev);
> +
> + free_irq(thermal->irq, thermal);
> + cancel_delayed_work_sync(&thermal->work);
> + thermal_zone_device_unregister(thermal->zone);
> + return 0;
> +}
> +
> +static struct platform_driver da9062_thermal_driver = {
> + .probe = da9062_thermal_probe,
> + .remove = da9062_thermal_remove,
> + .driver = {
> + .name = "da9062-thermal",
> + .of_match_table = da9062_compatible_reg_id_table,
> + },
> +};
> +
> +module_platform_driver(da9062_thermal_driver);
> +
> +MODULE_AUTHOR("Steve Twiss");
> +MODULE_DESCRIPTION("Thermal TJUNC device driver for Dialog DA9062 and DA9061");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:da9062-thermal");
> --
> end-of-patch for PATCH V7
>
^ permalink raw reply
* Re: [PATCH V4 2/2] thermal: broadcom: add Northstar thermal driver
From: Eduardo Valentin @ 2017-04-01 19:54 UTC (permalink / raw)
To: Rafał Miłecki
Cc: Zhang Rui, Rob Herring, Mark Rutland, Stephen Warren, Lee Jones,
Eric Anholt, Florian Fainelli, Ray Jui, Scott Branden,
bcm-kernel-feedback-list, linux-pm, devicetree, linux-rpi-kernel,
linux-arm-kernel, Rafał Miłecki, Jon Mason
In-Reply-To: <20170331201124.656-2-zajec5@gmail.com>
On Fri, Mar 31, 2017 at 10:11:24PM +0200, Rafał Miłecki wrote:
> From: Rafał Miłecki <rafal@milecki.pl>
>
> Northstar is a SoC family commonly used in home routers. This commit
> adds a driver for checking CPU temperature. As Northstar Plus seems to
> also have this IP block this new symbol gets ARCH_BCM_IPROC dependency.
>
> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
> Signed-off-by: Jon Mason <jon.mason@broadcom.com>
> ---
This driver looks fine from what concerns the of thermal usage.
I had only one request on the DT bindings example. I believe better to
get the example fixed so bad DTs does not get copied.
> V2: Make it iProc specific as NSP can also use this driver
> Select proper symbols in config ARCH_BCM_IPROC
> Define PVTMON register bits
> Update code selecting temperature monitor mode
> Thank you Jon!
> V3: More details in help message for BCM_NS_THERMAL
> Use slope & offset
> Drop arch code change (I'll be submitted using a proper tree)
> Thank you Eduardo!
> V4: Comment operations on PVTMON_CONTROL0 register
> ---
> drivers/thermal/Kconfig | 5 ++
> drivers/thermal/Makefile | 1 +
> drivers/thermal/broadcom/Kconfig | 8 +++
> drivers/thermal/broadcom/Makefile | 1 +
> drivers/thermal/broadcom/ns-thermal.c | 105 ++++++++++++++++++++++++++++++++++
Also, I have just merged a BRCM driver. Does it make sense to move it
here too?
It does not need to be a blocking request for this driver though.
> 5 files changed, 120 insertions(+)
> create mode 100644 drivers/thermal/broadcom/Kconfig
> create mode 100644 drivers/thermal/broadcom/Makefile
> create mode 100644 drivers/thermal/broadcom/ns-thermal.c
>
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 776b34396144..008e173ec825 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -392,6 +392,11 @@ config MTK_THERMAL
> Enable this option if you want to have support for thermal management
> controller present in Mediatek SoCs
>
> +menu "Broadcom thermal drivers"
> +depends on ARCH_BCM || COMPILE_TEST
> +source "drivers/thermal/broadcom/Kconfig"
> +endmenu
> +
> menu "Texas Instruments thermal drivers"
> depends on ARCH_HAS_BANDGAP || COMPILE_TEST
> depends on HAS_IOMEM
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index 7adae2029355..549d81b6363c 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -27,6 +27,7 @@ thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o
> thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
>
> # platform thermal drivers
> +obj-y += broadcom/
> obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o
> obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
> obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
> diff --git a/drivers/thermal/broadcom/Kconfig b/drivers/thermal/broadcom/Kconfig
> new file mode 100644
> index 000000000000..f0dea8a8e002
> --- /dev/null
> +++ b/drivers/thermal/broadcom/Kconfig
> @@ -0,0 +1,8 @@
> +config BCM_NS_THERMAL
> + tristate "Northstar thermal driver"
> + depends on ARCH_BCM_IPROC || COMPILE_TEST
> + help
> + Northstar is a family of SoCs that includes e.g. BCM4708, BCM47081,
> + BCM4709 and BCM47094. It contains DMU (Device Management Unit) block
> + with a thermal sensor that allows checking CPU temperature. This
> + driver provides support for it.
> diff --git a/drivers/thermal/broadcom/Makefile b/drivers/thermal/broadcom/Makefile
> new file mode 100644
> index 000000000000..059df9a0ed69
> --- /dev/null
> +++ b/drivers/thermal/broadcom/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_BCM_NS_THERMAL) += ns-thermal.o
> diff --git a/drivers/thermal/broadcom/ns-thermal.c b/drivers/thermal/broadcom/ns-thermal.c
> new file mode 100644
> index 000000000000..eab96b3572b9
> --- /dev/null
> +++ b/drivers/thermal/broadcom/ns-thermal.c
> @@ -0,0 +1,105 @@
> +/*
> + * Copyright (C) 2017 Rafał Miłecki <rafal@milecki.pl>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +#include <linux/thermal.h>
> +
> +#define PVTMON_CONTROL0 0x00
> +#define PVTMON_CONTROL0_SEL_MASK 0x0000000e
> +#define PVTMON_CONTROL0_SEL_TEMP_MONITOR 0x00000000
> +#define PVTMON_CONTROL0_SEL_TEST_MODE 0x0000000e
> +#define PVTMON_STATUS 0x08
> +
> +struct ns_thermal {
> + struct thermal_zone_device *tz;
> + void __iomem *pvtmon;
> +};
> +
> +static int ns_thermal_get_temp(void *data, int *temp)
> +{
> + struct ns_thermal *ns_thermal = data;
> + int offset = thermal_zone_get_offset(ns_thermal->tz);
> + int slope = thermal_zone_get_slope(ns_thermal->tz);
> + u32 val;
> +
> + val = readl(ns_thermal->pvtmon + PVTMON_CONTROL0);
> + if ((val & PVTMON_CONTROL0_SEL_MASK) != PVTMON_CONTROL0_SEL_TEMP_MONITOR) {
> + /* Clear current mode selection */
> + val &= ~PVTMON_CONTROL0_SEL_MASK;
> +
> + /* Set temp monitor mode (it's the default actually) */
> + val |= PVTMON_CONTROL0_SEL_TEMP_MONITOR;
> +
> + writel(val, ns_thermal->pvtmon + PVTMON_CONTROL0);
> + }
> +
> + val = readl(ns_thermal->pvtmon + PVTMON_STATUS);
> + *temp = slope * val + offset;
> +
> + return 0;
> +}
> +
> +const struct thermal_zone_of_device_ops ns_thermal_ops = {
> + .get_temp = ns_thermal_get_temp,
> +};
> +
> +static int ns_thermal_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct ns_thermal *ns_thermal;
> +
> + ns_thermal = devm_kzalloc(dev, sizeof(*ns_thermal), GFP_KERNEL);
> + if (!ns_thermal)
> + return -ENOMEM;
> +
> + ns_thermal->pvtmon = of_iomap(dev_of_node(dev), 0);
> + if (WARN_ON(!ns_thermal->pvtmon))
> + return -ENOENT;
> +
> + ns_thermal->tz = devm_thermal_zone_of_sensor_register(dev, 0,
> + ns_thermal,
> + &ns_thermal_ops);
> + if (IS_ERR(ns_thermal->tz)) {
> + iounmap(ns_thermal->pvtmon);
> + return PTR_ERR(ns_thermal->tz);
> + }
> +
> + platform_set_drvdata(pdev, ns_thermal);
> +
> + return 0;
> +}
> +
> +static int ns_thermal_remove(struct platform_device *pdev)
> +{
> + struct ns_thermal *ns_thermal = platform_get_drvdata(pdev);
> +
> + iounmap(ns_thermal->pvtmon);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id ns_thermal_of_match[] = {
> + { .compatible = "brcm,ns-thermal", },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, ns_thermal_of_match);
> +
> +static struct platform_driver ns_thermal_driver = {
> + .probe = ns_thermal_probe,
> + .remove = ns_thermal_remove,
> + .driver = {
> + .name = "ns-thermal",
> + .of_match_table = ns_thermal_of_match,
> + },
> +};
> +module_platform_driver(ns_thermal_driver);
> +
> +MODULE_DESCRIPTION("Northstar thermal driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.11.0
>
^ permalink raw reply
* Re: [PATCH V4 1/2] dt-bindings: thermal: add support for Broadcom's Northstar thermal
From: Eduardo Valentin @ 2017-04-01 19:51 UTC (permalink / raw)
To: Rafał Miłecki
Cc: Zhang Rui, Rob Herring, Mark Rutland, Stephen Warren, Lee Jones,
Eric Anholt, Florian Fainelli, Ray Jui, Scott Branden,
bcm-kernel-feedback-list, linux-pm, devicetree, linux-rpi-kernel,
linux-arm-kernel, Rafał Miłecki
In-Reply-To: <20170331201124.656-1-zajec5@gmail.com>
Rafal,
On Fri, Mar 31, 2017 at 10:11:23PM +0200, Rafał Miłecki wrote:
> From: Rafał Miłecki <rafal@milecki.pl>
>
> This commit documents binding for thermal used in Northstar family SoCs.
>
> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
> ---
> V3: Add thermal-zones to the example
> Rob: Because of this update, I didn't include Acked-by I got for V2
> ---
> .../devicetree/bindings/thermal/brcm,ns-thermal | 26 ++++++++++++++++++++++
> 1 file changed, 26 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/thermal/brcm,ns-thermal
>
> diff --git a/Documentation/devicetree/bindings/thermal/brcm,ns-thermal b/Documentation/devicetree/bindings/thermal/brcm,ns-thermal
> new file mode 100644
> index 000000000000..c561c7349f17
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/thermal/brcm,ns-thermal
> @@ -0,0 +1,26 @@
> +* Broadcom Northstar Thermal
> +
> +This binding describes thermal sensor that is part of Northstar's DMU (Device
> +Management Unit).
> +
> +Required properties:
> +- compatible : Must be "brcm,ns-thermal"
> +- reg : iomem address range of PVTMON registers
> +- #thermal-sensor-cells : Should be <0>
> +
> +Example:
> +
> +thermal: thermal@1800c2c0 {
> + compatible = "brcm,ns-thermal";
> + reg = <0x1800c2c0 0x10>;
> + #thermal-sensor-cells = <0>;
> +};
> +
> +thermal-zones {
> + cpu_thermal: cpu-thermal {
> + polling-delay-passive = <0>;
> + polling-delay = <1000>;
> + coefficients = <(-556) 418000>;
> + thermal-sensors = <&thermal>;
You need to define trips and cooling devices here. Otherwise, makes
little sense to have this device in thermal subsystem. Here is an
example of minimal set:
https://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git/commit/?h=linus&id=1e2ac9821de6a85d3e8358f238436708d1d46869
The above has no passive action. It is just gonna shutdown the system if
temperature crosses a threshold.
But, a typical cooling device would be CPU frequency throttling. Do you have
that up and running in your routers?
> + };
> +};
> --
> 2.11.0
>
^ permalink raw reply
* Re: [PATCH V12 3/4] ARM64: dts: bcm2837: Define CPU thermal coefficients
From: Eduardo Valentin @ 2017-04-01 16:37 UTC (permalink / raw)
To: Stefan Wahren
Cc: Zhang Rui, kernel, Eric Anholt, Rob Herring, Frank Rowand,
Florian Fainelli, Rafał Miłecki, linux-rpi-kernel,
devicetree, linux-pm
In-Reply-To: <1490990586-30898-4-git-send-email-stefan.wahren@i2se.com>
On Fri, Mar 31, 2017 at 08:03:05PM +0000, Stefan Wahren wrote:
> This defines the bcm2837 SoC specific thermal coefficients in
> order to initialize the thermal driver correctly.
>
> Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
Acked-by: Eduardo Valentin <edubezval@gmail.com>
^ permalink raw reply
* Re: [PATCH V12 2/4] ARM: dts: bcm283x: Add CPU thermal zone with 1 trip point
From: Eduardo Valentin @ 2017-04-01 16:37 UTC (permalink / raw)
To: Stefan Wahren
Cc: Zhang Rui, kernel, Eric Anholt, Rob Herring, Frank Rowand,
Florian Fainelli, Rafał Miłecki, linux-rpi-kernel,
devicetree, linux-pm
In-Reply-To: <1490990586-30898-3-git-send-email-stefan.wahren@i2se.com>
On Fri, Mar 31, 2017 at 08:03:04PM +0000, Stefan Wahren wrote:
> As suggested by Eduardo Valentin this adds the thermal zone for
> the bcm2835 SoC with its single thermal sensor. We start with
> the criticial trip point and leave the cooling devices empty
> since we don't have any at the moment. Since the coefficients
> could vary depending on the SoC we need to define them separate.
>
> Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
Acked-by: Eduardo Valentin <edubezval@gmail.com>
^ permalink raw reply
* Re: [PATCH V12 0/4] thermal: bcm2835: add thermal driver for bcm2835 SoC
From: Eduardo Valentin @ 2017-04-01 16:33 UTC (permalink / raw)
To: Stefan Wahren
Cc: Zhang Rui, kernel, Eric Anholt, Rob Herring, Frank Rowand,
Florian Fainelli, Rafał Miłecki, linux-rpi-kernel,
devicetree, linux-pm
In-Reply-To: <1490990586-30898-1-git-send-email-stefan.wahren@i2se.com>
Hello Stefan,
On Fri, Mar 31, 2017 at 08:03:02PM +0000, Stefan Wahren wrote:
> This is an attempt to finish Martin's great work on the bcm2835
> thermal driver. It includes now all Eduardo's suggestions and the
> explanations from the Raspberry Pi forum [1].
>
> ChangeLog:
> V1 -> V2: added specific settings depending on compatiblity
> added trip point based on register
> setting up ctrl-register if HW is not enabled by firmware
> as per recommendation of Eric (untested)
> check that clock frequency is in range
> (1.9 - 5MHz - as per comment in clk-bcm2835.c)
> V2 -> V4: moved back to thermal (not using bcm sub-directory)
> set polling interval to 1second (was 0ms, so interrupt driven)
> V5 -> V6: added correct depends in KConfig
> removed defined default for RESET_DELAY
> removed obvious comments
> clarify HW setup comments if not set up by FW already
> move clk_prepare_enable to an earlier stage and add error handling
> clarify warning when TS-clock runs out of recommended range
> clk_disable_unprepare added in bcm2835_thermal_remove
> added comment on recommended temperature ranges for SOC
> V6 -> V7: removed depends on ARCH_BCM2836 || ARCH_BCM2837 in Kconfig
> V7 -> V8: rebased
> V8 -> V9: moved to use the thermal framework offset and slope in
> thermal_zone_parameters as per request
> V9 -> V10: implement support for thermal zone descriptor, define offset and
> slope within DT, apply forum explanations, replace symbolic with octal
> permissions
> V10 -> V11: fix parse issue in bcm2837.dtsi, fix probing and remove unused tzp
> V11 -> V12: split of-thermal changes from this series since they aren't
> necessary, avoid double definition of matching table
>
> [1] - https://www.raspberrypi.org/forums/viewtopic.php?f=72&t=160289&p=1040448
>
> Stefan Wahren (4):
> dt-bindings: Add thermal zone to bcm2835-thermal example
> ARM: dts: bcm283x: Add CPU thermal zone with 1 trip point
> ARM64: dts: bcm2837: Define CPU thermal coefficients
> thermal: bcm2835: add thermal driver for bcm2835 SoC
Thanks for the patience and for cleaning the driver. I added patches 1
and 4 into my -linus branch for the next merge window. DTS(i) changes
should go via your arch tree.
BR,
^ permalink raw reply
* Re: [PATCH RFC 2/3] thermal: dove: convert to a thermal OF sensor device
From: Eduardo Valentin @ 2017-04-01 16:15 UTC (permalink / raw)
To: Russell King
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory Clement,
Rob Herring, Mark Rutland, Zhang Rui, linux-arm-kernel,
devicetree, linux-pm
In-Reply-To: <E1cn8qH-0002v6-SE@rmk-PC.armlinux.org.uk>
Russell,
On Sun, Mar 12, 2017 at 07:07:45PM +0000, Russell King wrote:
> Convert the dove thermal infrastructure to an OF sensor device, and add
> the thermal zones for the SoC, with a critical trip point of 120°C.
> This allows us to specify thermal zones and couple them to cooling
> devices in DT.
>
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
> ---
> arch/arm/boot/dts/dove.dtsi | 17 +++++++++++++++++
> drivers/thermal/dove_thermal.c | 33 +++++++++++++++++++++++++--------
I have no opposition to these changes. The only request, to avoid
conflicts, is to split the patch into driver and DTS changes. We have
been pushing these separately. DTS changes go via the arch tree. Drivers
changes goes via Rui/me.
You can add my:
Acked-by: Eduardo Valentin <edubezval@gmail.com>
On the DTSI patch.
^ permalink raw reply
* [PATCH 1/1] clk: meson: gxbb: remove the "cpu_clk" from the GXBB and GXL driver
From: Martin Blumenstingl @ 2017-04-01 12:55 UTC (permalink / raw)
To: linux-amlogic, jbrunet, narmstrong, linux-clk
Cc: devicetree, khilman, carlo, sboyd, mturquette, linux-arm-kernel,
Martin Blumenstingl
In-Reply-To: <20170401125519.7339-1-martin.blumenstingl@googlemail.com>
It seems that the "cpu_clk" was carried over from the meson8b clock
controller driver. On Meson GX (GXBB/GXL/GXM) the registers which are
used by the cpu_clk have a different purpose (in other words: they don't
control the CPU clock anymore). HHI_SYS_CPU_CLK_CNTL1 bits 31:24 are
reserved according to the public S905 datasheet, while bit 23 is the
"A53_trace_clk_DIS" gate (which according to the datasheet should only
be used in case a silicon bug is discovered) and bits 22:20 are a
divider (A53_trace_clk). The meson clk-cpu code however expects that
bits 28:20 are reserved for a divider (according to the public S805
datasheet this "SCALE_DIV: This value represents an N+1 divider of the
input clock.").
The CPU clock on Meson GX SoCs is provided by the SCPI DVFS clock
driver instead. Two examples from a Meson GXL S905X SoC:
- vcpu (SCPI DVFS clock 0) rate: 1000000000 / cpu_clk rate: 708000000
- vcpu (SCPI DVFS clock 0) rate: 1512000000 / cpu_clk rate: 708000000
Unfortunately the CLKID_CPUCLK was already exported (but is currently
not used) to DT. Due to the removal of this clock definition there is
now a hole in the clk_hw_onecell_data (which is not a problem because
this case is already handled in gxbb_clkc_probe).
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
drivers/clk/meson/gxbb.c | 64 ++---------------------------------
drivers/clk/meson/gxbb.h | 2 +-
include/dt-bindings/clock/gxbb-clkc.h | 1 -
3 files changed, 4 insertions(+), 63 deletions(-)
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index ad5f027af1a2..7cf88ca9bdce 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -278,20 +278,6 @@ static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
{ /* sentinel */ },
};
-static const struct clk_div_table cpu_div_table[] = {
- { .val = 1, .div = 1 },
- { .val = 2, .div = 2 },
- { .val = 3, .div = 3 },
- { .val = 2, .div = 4 },
- { .val = 3, .div = 6 },
- { .val = 4, .div = 8 },
- { .val = 5, .div = 10 },
- { .val = 6, .div = 12 },
- { .val = 7, .div = 14 },
- { .val = 8, .div = 16 },
- { /* sentinel */ },
-};
-
static struct meson_clk_pll gxbb_fixed_pll = {
.m = {
.reg_off = HHI_MPLL_CNTL,
@@ -612,21 +598,10 @@ static struct meson_clk_mpll gxbb_mpll2 = {
};
/*
- * FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL
- * post-dividers and should be modeled with their respective PLLs via the
- * forthcoming coordinated clock rates feature
+ * FIXME The legacy composite clocks (e.g. clk81) are both PLL post-dividers
+ * and should be modeled with their respective PLLs via the forthcoming
+ * coordinated clock rates feature
*/
-static struct meson_clk_cpu gxbb_cpu_clk = {
- .reg_off = HHI_SYS_CPU_CLK_CNTL1,
- .div_table = cpu_div_table,
- .clk_nb.notifier_call = meson_clk_cpu_notifier_cb,
- .hw.init = &(struct clk_init_data){
- .name = "cpu_clk",
- .ops = &meson_clk_cpu_ops,
- .parent_names = (const char *[]){ "sys_pll" },
- .num_parents = 1,
- },
-};
static u32 mux_table_clk81[] = { 6, 5, 7 };
@@ -1045,7 +1020,6 @@ static MESON_GATE(gxbb_ao_i2c, HHI_GCLK_AO, 4);
static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
.hws = {
[CLKID_SYS_PLL] = &gxbb_sys_pll.hw,
- [CLKID_CPUCLK] = &gxbb_cpu_clk.hw,
[CLKID_HDMI_PLL] = &gxbb_hdmi_pll.hw,
[CLKID_FIXED_PLL] = &gxbb_fixed_pll.hw,
[CLKID_FCLK_DIV2] = &gxbb_fclk_div2.hw,
@@ -1165,7 +1139,6 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
static struct clk_hw_onecell_data gxl_hw_onecell_data = {
.hws = {
[CLKID_SYS_PLL] = &gxbb_sys_pll.hw,
- [CLKID_CPUCLK] = &gxbb_cpu_clk.hw,
[CLKID_HDMI_PLL] = &gxbb_hdmi_pll.hw,
[CLKID_FIXED_PLL] = &gxbb_fixed_pll.hw,
[CLKID_FCLK_DIV2] = &gxbb_fclk_div2.hw,
@@ -1430,7 +1403,6 @@ struct clkc_data {
unsigned int clk_dividers_count;
struct meson_clk_audio_divider *const *clk_audio_dividers;
unsigned int clk_audio_dividers_count;
- struct meson_clk_cpu *cpu_clk;
struct clk_hw_onecell_data *hw_onecell_data;
};
@@ -1447,7 +1419,6 @@ static const struct clkc_data gxbb_clkc_data = {
.clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers),
.clk_audio_dividers = gxbb_audio_dividers,
.clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers),
- .cpu_clk = &gxbb_cpu_clk,
.hw_onecell_data = &gxbb_hw_onecell_data,
};
@@ -1464,7 +1435,6 @@ static const struct clkc_data gxl_clkc_data = {
.clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers),
.clk_audio_dividers = gxbb_audio_dividers,
.clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers),
- .cpu_clk = &gxbb_cpu_clk,
.hw_onecell_data = &gxl_hw_onecell_data,
};
@@ -1479,8 +1449,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
const struct clkc_data *clkc_data;
void __iomem *clk_base;
int ret, clkid, i;
- struct clk_hw *parent_hw;
- struct clk *parent_clk;
struct device *dev = &pdev->dev;
clkc_data = of_device_get_match_data(&pdev->dev);
@@ -1502,9 +1470,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
for (i = 0; i < clkc_data->clk_mplls_count; i++)
clkc_data->clk_mplls[i]->base = clk_base;
- /* Populate the base address for CPU clk */
- clkc_data->cpu_clk->base = clk_base;
-
/* Populate base address for gates */
for (i = 0; i < clkc_data->clk_gates_count; i++)
clkc_data->clk_gates[i]->reg = clk_base +
@@ -1538,29 +1503,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
goto iounmap;
}
- /*
- * Register CPU clk notifier
- *
- * FIXME this is wrong for a lot of reasons. First, the muxes should be
- * struct clk_hw objects. Second, we shouldn't program the muxes in
- * notifier handlers. The tricky programming sequence will be handled
- * by the forthcoming coordinated clock rates mechanism once that
- * feature is released.
- *
- * Furthermore, looking up the parent this way is terrible. At some
- * point we will stop allocating a default struct clk when registering
- * a new clk_hw, and this hack will no longer work. Releasing the ccr
- * feature before that time solves the problem :-)
- */
- parent_hw = clk_hw_get_parent(&clkc_data->cpu_clk->hw);
- parent_clk = parent_hw->clk;
- ret = clk_notifier_register(parent_clk, &clkc_data->cpu_clk->clk_nb);
- if (ret) {
- pr_err("%s: failed to register clock notifier for cpu_clk\n",
- __func__);
- goto iounmap;
- }
-
return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
clkc_data->hw_onecell_data);
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
index 17c6aef033ff..36330c2d4433 100644
--- a/drivers/clk/meson/gxbb.h
+++ b/drivers/clk/meson/gxbb.h
@@ -171,7 +171,7 @@
* to be exposed to client nodes in DT: include/dt-bindings/clock/gxbb-clkc.h
*/
#define CLKID_SYS_PLL 0
-/* CLKID_CPUCLK */
+/* ID 1 is unused (it was used by the non-existing CLKID_CPUCLK before) */
/* CLKID_HDMI_PLL */
#define CLKID_FIXED_PLL 3
/* CLKID_FCLK_DIV2 */
diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
index 4516bc4253b5..54faf83a4851 100644
--- a/include/dt-bindings/clock/gxbb-clkc.h
+++ b/include/dt-bindings/clock/gxbb-clkc.h
@@ -5,7 +5,6 @@
#ifndef __GXBB_CLKC_H
#define __GXBB_CLKC_H
-#define CLKID_CPUCLK 1
#define CLKID_HDMI_PLL 2
#define CLKID_FCLK_DIV2 4
#define CLKID_FCLK_DIV3 5
--
2.12.1
^ permalink raw reply related
* [PATCH 0/1] remove the "cpu_clk" from the GXBB/GXL/GXM driver
From: Martin Blumenstingl @ 2017-04-01 12:55 UTC (permalink / raw)
To: linux-amlogic, jbrunet, narmstrong, linux-clk
Cc: devicetree, khilman, carlo, sboyd, mturquette, linux-arm-kernel,
Martin Blumenstingl
This is the updated version of my RFC patch from [0].
The quick summary for this patch is that the "cpu_clk" seems to have
been copied from the Meson8b clock driver when the GXBB clock driver
was initially added. However, on GXBB (and the other GX SoCs) the
actual CPU clock is provided by a SCPI DVFS clock.
More details can be found in the patch description itself.
This was tested on a Khadas VIM board (GXL S905X).
Changes since the RFC version:
- rebased to the "clk-meson" branch (e65ae3fb97b4 "dt-bindings: clock:
gxbb-clkc: Add GXL compatible variant") and Jerome's audio clock
patches (in version 2: [1])
- remove the now unused cpu_div_table (which was left over in the RFC
version)
- slightly updated the comment for the now unused clock ID 1 in
drivers/clk/meson/gxbb.h
[0] https://patchwork.kernel.org/patch/9644993/
[1] http://lists.infradead.org/pipermail/linux-amlogic/2017-March/003200.html
Martin Blumenstingl (1):
clk: meson: gxbb: remove the "cpu_clk" from the GXBB and GXL driver
drivers/clk/meson/gxbb.c | 64 ++---------------------------------
drivers/clk/meson/gxbb.h | 2 +-
include/dt-bindings/clock/gxbb-clkc.h | 1 -
3 files changed, 4 insertions(+), 63 deletions(-)
--
2.12.1
^ permalink raw reply
* Re: [PATCH v5 1/2] Documentation: dt-bindings: Document bindings for Aspeed ADC
From: Jonathan Cameron @ 2017-04-01 10:51 UTC (permalink / raw)
To: Joel Stanley, Rick Altherr
Cc: OpenBMC Maillist, Linux Kernel Mailing List,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-iio-u79uwXL29TY76Z2rM5mHXA, Hartmut Knaack, Rob Herring,
Lars-Peter Clausen, Mark Rutland, Peter Meerwald-Stadler
In-Reply-To: <CACPK8Xcf2A8RMy7cthJrdi2CA0L_Hfi+2Hy3JBCzLTsofjhEuA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On 29/03/17 03:33, Joel Stanley wrote:
> On Wed, Mar 29, 2017 at 8:22 AM, Rick Altherr <raltherr-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org> wrote:
>> Signed-off-by: Rick Altherr <raltherr-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
>> ---
>
> Acked-by: Joel Stanley <joel-U3u1mxZcP9KHXe+LvDLADg@public.gmane.org>
I can't see why Rob would mind any of the changes made since he
Acked this (and having acked it I doubt he is looking at newer versions!)
so I'm going to take the view his Ack still applies.
Applied to the togreg branch of iio.git which will get pushed out first
as testing for the autobuilders to have a chance to play with it.
Thanks,
Jonathan
>
>>
>> Changes in v5: None
>> Changes in v4: None
>> Changes in v3:
>> - Consistently write hex contstants with lowercase letters
>> - Drop model numbers from description as same IP is used in every generation
>>
>> Changes in v2:
>> - Rewritten as an IIO ADC device
>>
>> .../devicetree/bindings/iio/adc/aspeed_adc.txt | 20 ++++++++++++++++++++
>> 1 file changed, 20 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/iio/adc/aspeed_adc.txt
>>
>> diff --git a/Documentation/devicetree/bindings/iio/adc/aspeed_adc.txt b/Documentation/devicetree/bindings/iio/adc/aspeed_adc.txt
>> new file mode 100644
>> index 000000000000..674e133b7cd7
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/iio/adc/aspeed_adc.txt
>> @@ -0,0 +1,20 @@
>> +Aspeed ADC
>> +
>> +This device is a 10-bit converter for 16 voltage channels. All inputs are
>> +single ended.
>> +
>> +Required properties:
>> +- compatible: Should be "aspeed,ast2400-adc" or "aspeed,ast2500-adc"
>> +- reg: memory window mapping address and length
>> +- clocks: Input clock used to derive the sample clock. Expected to be the
>> + SoC's APB clock.
>> +- #io-channel-cells: Must be set to <1> to indicate channels are selected
>> + by index.
>> +
>> +Example:
>> + adc@1e6e9000 {
>> + compatible = "aspeed,ast2400-adc";
>> + reg = <0x1e6e9000 0xb0>;
>> + clocks = <&clk_apb>;
>> + #io-channel-cells = <1>;
>> + };
>> --
>> 2.12.2.564.g063fe858b8-goog
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: [PATCH V8 5/6] ACPI: Support the probing on the devices which apply indirect-IO
From: Rafael J. Wysocki @ 2017-04-01 9:52 UTC (permalink / raw)
To: zhichang.yuan
Cc: Rafael J. Wysocki, zhichang.yuan, Rafael J. Wysocki,
Catalin Marinas, Will Deacon, Rob Herring, Frank Rowand,
Bjorn Helgaas, Arnd Bergmann,
linux-arm-kernel@lists.infradead.org, Mark Rutland, Brian Starkey,
Olof Johansson, Lorenzo Pieralisi, Benjamin Herrenschmidt,
Linux Kernel Mailing List, ACPI Devel Maling List, linuxar
In-Reply-To: <bfdf2de0-c309-0139-4075-dfcd678b6d51@gmail.com>
On Sat, Apr 1, 2017 at 4:16 AM, zhichang.yuan <zhichang.yuan02@gmail.com> wrote:
>
>
> On 04/01/2017 07:02 AM, Rafael J. Wysocki wrote:
>> On Fri, Mar 31, 2017 at 8:52 AM, zhichang.yuan
>> <yuanzhichang@hisilicon.com> wrote:
>>> Hi, Rafael,
>>>
>>> Thanks for reviewing this!
>>>
>>> On 2017/3/31 4:31, Rafael J. Wysocki wrote:
>>>> On Thursday, March 30, 2017 11:26:58 PM zhichang.yuan wrote:
>>>>> On some platforms(such as Hip06/Hip07), the legacy ISA/LPC devices access I/O
>>>>> with some special host-local I/O ports known on x86. To access the I/O
>>>>> peripherals, an indirect-IO mechanism is introduced to mapped the host-local
>>>>> I/O to system logical/fake PIO similar the PCI MMIO on architectures where no
>>>>> separate I/O space exists. Just as PCI MMIO, the host I/O range should be
>>>>> registered before probing the downstream devices and set up the I/O mapping.
>>>>> But current ACPI bus probing doesn't support these indirect-IO hosts/devices.
>>>>>
>>>>> This patch introdueces a new ACPI handler for this device category. Through the
>>>>> handler attach callback, the indirect-IO hosts I/O registration is done and
>>>>> all peripherals' I/O resources are translated into logic/fake PIO before
>>>>> starting the enumeration.
>>>>
>>>> Can you explain to me briefly what exactly this code is expected to be doing?
>>>
>>> As you know currently for ARM architecture IO space is memory mapped and
>>> is only used by pci devices. The port number is dynamically allocated
>>> converting the device IO address into a PIO token: i.e.
>>> http://lxr.free-electrons.com/source/drivers/acpi/pci_root.c#L745
>>> This patch is meant to support a new class of IO host controller
>>> that are not PCI based and that still require to have the IO addresses
>>> be translated in the same PIO token space as the PCI controller
>>
>> IOW, this is ARM-specific, right?
>
> Yes. The current host added in this patch with _HID "HISI0191" is on ARM64.
But the underlying mechanism is ARM-specific as well AFAICS.
> But, I think the handler driver is architecture dependent.
I guess you mean "independent"? That doesn't matter.
If ARM64 is the only architecture to use it in foreseeable future
(which is the case for all I can say), it should go into acpi/arm64/
and please ask the maintainers thereof to review it.
Thanks,
Rafael
^ permalink raw reply
* Re: [PATCH v2 2/2] phy: meson: add USB2 PHY support for Meson GXL and GXM
From: Martin Blumenstingl @ 2017-04-01 9:37 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
hendrik-MJglGmTD+GWCT0AhDRffsw, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
carlo-KA+7E9HrN00dnm+yROfE0A, khilman-rdvid1DuHRBWk0Htik3J/w
In-Reply-To: <82edc36e-80ae-3aa2-cd45-664b26a21e4a-l0cyMroinI0@public.gmane.org>
Hi Kishon,
On Wed, Mar 29, 2017 at 12:56 PM, Kishon Vijay Abraham I <kishon-l0cyMroinI0@public.gmane.org> wrote:
> Hi,
>
> On Wednesday 29 March 2017 03:03 AM, Martin Blumenstingl wrote:
>> Hi Kishon,
>>
>> On Sat, Mar 18, 2017 at 2:00 PM, Martin Blumenstingl
>> <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> wrote:
>>> This adds a new driver for the USB2 PHYs found on Meson GXL and GXM SoCs
>>> (both SoCs are using the same USB PHY register layout).
>>>
>>> The USB2 PHY is a simple PHY which only has a few registers to configure
>>> the mode (host/device) and a reset register (to enable/disable the PHY).
>>>
>>> Unfortunately there are no datasheets available for this PHY. The driver
>>> was written by reading the code from Amlogic's GPL kernel sources and
>>> by analyzing the registers on an actual GXL and GXM device running the
>>> kernel that was shipped on the boards I have.
>> gentle ping - did you have time to review this patch in v2 yet?
>
> Have a few comments, see below..
thanks for taking the time to review this!
>>
>>> Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
>>> ---
>>> drivers/phy/Kconfig | 14 ++
>>> drivers/phy/Makefile | 1 +
>>> drivers/phy/phy-meson-gxl-usb2.c | 273 +++++++++++++++++++++++++++++++++++++++
>>> 3 files changed, 288 insertions(+)
>>> create mode 100644 drivers/phy/phy-meson-gxl-usb2.c
>>>
>>> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
>>> index dc5277ad1b5a..2573e139fd17 100644
>>> --- a/drivers/phy/Kconfig
>>> +++ b/drivers/phy/Kconfig
>>> @@ -510,6 +510,19 @@ config PHY_MESON8B_USB2
>>> and GXBB SoCs.
>>> If unsure, say N.
>>>
>>> +config PHY_MESON_GXL_USB
>>> + tristate "Meson GXL and GXM USB2 PHY drivers"
>>> + default ARCH_MESON
>>> + depends on OF && (ARCH_MESON || COMPILE_TEST)
>>> + depends on USB_SUPPORT
>>> + select USB_COMMON
>>> + select GENERIC_PHY
>>> + select REGMAP_MMIO
>>> + help
>>> + Enable this to support the Meson USB2 PHYs found in Meson
>>> + GXL and GXM SoCs.
>>> + If unsure, say N.
>>> +
>>> config PHY_NSP_USB3
>>> tristate "Broadcom NorthStar plus USB3 PHY driver"
>>> depends on OF && (ARCH_BCM_NSP || COMPILE_TEST)
>>> @@ -518,4 +531,5 @@ config PHY_NSP_USB3
>>> help
>>> Enable this to support the Broadcom Northstar plus USB3 PHY.
>>> If unsure, say N.
>>> +
>
> spurious space..
you're right, this shouldn't be here. I'll fix this in the next version
>>> endmenu
>>> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
>>> index e7b0feb1e125..e680b856e38e 100644
>>> --- a/drivers/phy/Makefile
>>> +++ b/drivers/phy/Makefile
>>> @@ -62,4 +62,5 @@ obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o
>>> obj-$(CONFIG_ARCH_TEGRA) += tegra/
>>> obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o
>>> obj-$(CONFIG_PHY_MESON8B_USB2) += phy-meson8b-usb2.o
>>> +obj-$(CONFIG_PHY_MESON_GXL_USB) += phy-meson-gxl-usb2.o
>>> obj-$(CONFIG_PHY_NSP_USB3) += phy-bcm-nsp-usb3.o
>>> diff --git a/drivers/phy/phy-meson-gxl-usb2.c b/drivers/phy/phy-meson-gxl-usb2.c
>>> new file mode 100644
>>> index 000000000000..4bf646a52c45
>>> --- /dev/null
>>> +++ b/drivers/phy/phy-meson-gxl-usb2.c
>>> @@ -0,0 +1,273 @@
>>> +/*
>>> + * Meson GXL and GXM USB2 PHY driver
>>> + *
>>> + * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#include <linux/delay.h>
>>> +#include <linux/io.h>
>>> +#include <linux/module.h>
>>> +#include <linux/of_device.h>
>>> +#include <linux/regmap.h>
>>> +#include <linux/phy/phy.h>
>>> +#include <linux/platform_device.h>
>>> +#include <linux/usb/of.h>
>>> +
>>> +/* bits [31:27] are read-only */
>>> +#define U2P_R0 0x0
>>> + #define U2P_R0_BYPASS_SEL BIT(0)
>>> + #define U2P_R0_BYPASS_DM_EN BIT(1)
>>> + #define U2P_R0_BYPASS_DP_EN BIT(2)
>>> + #define U2P_R0_TXBITSTUFF_ENH BIT(3)
>>> + #define U2P_R0_TXBITSTUFF_EN BIT(4)
>>> + #define U2P_R0_DM_PULLDOWN BIT(5)
>>> + #define U2P_R0_DP_PULLDOWN BIT(6)
>>> + #define U2P_R0_DP_VBUS_VLD_EXT_SEL BIT(7)
>>> + #define U2P_R0_DP_VBUS_VLD_EXT BIT(8)
>>> + #define U2P_R0_ADP_PRB_EN BIT(9)
>>> + #define U2P_R0_ADP_DISCHARGE BIT(10)
>>> + #define U2P_R0_ADP_CHARGE BIT(11)
>>> + #define U2P_R0_DRV_VBUS BIT(12)
>>> + #define U2P_R0_ID_PULLUP BIT(13)
>>> + #define U2P_R0_LOOPBACK_EN_B BIT(14)
>>> + #define U2P_R0_OTG_DISABLE BIT(15)
>>> + #define U2P_R0_COMMON_ONN BIT(16)
>>> + #define U2P_R0_FSEL_MASK GENMASK(19, 17)
>>> + #define U2P_R0_REF_CLK_SEL_MASK GENMASK(21, 20)
>>> + #define U2P_R0_POWER_ON_RESET BIT(22)
>>> + #define U2P_R0_V_ATE_TEST_EN_B_MASK GENMASK(24, 23)
>>> + #define U2P_R0_ID_SET_ID_DQ BIT(25)
>>> + #define U2P_R0_ATE_RESET BIT(26)
>>> + #define U2P_R0_FSV_MINUS BIT(27)
>>> + #define U2P_R0_FSV_PLUS BIT(28)
>>> + #define U2P_R0_BYPASS_DM_DATA BIT(29)
>>> + #define U2P_R0_BYPASS_DP_DATA BIT(30)
>>> +
>>> +#define U2P_R1 0x4
>>> + #define U2P_R1_BURN_IN_TEST BIT(0)
>>> + #define U2P_R1_ACA_ENABLE BIT(1)
>>> + #define U2P_R1_DCD_ENABLE BIT(2)
>>> + #define U2P_R1_VDAT_SRC_EN_B BIT(3)
>>> + #define U2P_R1_VDAT_DET_EN_B BIT(4)
>>> + #define U2P_R1_CHARGES_SEL BIT(5)
>>> + #define U2P_R1_TX_PREEMP_PULSE_TUNE BIT(6)
>>> + #define U2P_R1_TX_PREEMP_AMP_TUNE_MASK GENMASK(8, 7)
>>> + #define U2P_R1_TX_RES_TUNE_MASK GENMASK(10, 9)
>>> + #define U2P_R1_TX_RISE_TUNE_MASK GENMASK(12, 11)
>>> + #define U2P_R1_TX_VREF_TUNE_MASK GENMASK(16, 13)
>>> + #define U2P_R1_TX_FSLS_TUNE_MASK GENMASK(20, 17)
>>> + #define U2P_R1_TX_HSXV_TUNE_MASK GENMASK(22, 21)
>>> + #define U2P_R1_OTG_TUNE_MASK GENMASK(25, 23)
>>> + #define U2P_R1_SQRX_TUNE_MASK GENMASK(28, 26)
>>> + #define U2P_R1_COMP_DIS_TUNE_MASK GENMASK(31, 29)
>>> +
>>> +/* bits [31:14] are read-only */
>>> +#define U2P_R2 0x8
>>> + #define U2P_R2_DATA_IN_MASK GENMASK(3, 0)
>>> + #define U2P_R2_DATA_IN_EN_MASK GENMASK(7, 4)
>>> + #define U2P_R2_ADDR_MASK GENMASK(11, 8)
>>> + #define U2P_R2_DATA_OUT_SEL BIT(12)
>>> + #define U2P_R2_CLK BIT(13)
>>> + #define U2P_R2_DATA_OUT_MASK GENMASK(17, 14)
>>> + #define U2P_R2_ACA_PIN_RANGE_C BIT(18)
>>> + #define U2P_R2_ACA_PIN_RANGE_B BIT(19)
>>> + #define U2P_R2_ACA_PIN_RANGE_A BIT(20)
>>> + #define U2P_R2_ACA_PIN_GND BIT(21)
>>> + #define U2P_R2_ACA_PIN_FLOAT BIT(22)
>>> + #define U2P_R2_CHARGE_DETECT BIT(23)
>>> + #define U2P_R2_DEVICE_SESSION_VALID BIT(24)
>>> + #define U2P_R2_ADP_PROBE BIT(25)
>>> + #define U2P_R2_ADP_SENSE BIT(26)
>>> + #define U2P_R2_SESSION_END BIT(27)
>>> + #define U2P_R2_VBUS_VALID BIT(28)
>>> + #define U2P_R2_B_VALID BIT(29)
>>> + #define U2P_R2_A_VALID BIT(30)
>>> + #define U2P_R2_ID_DIG BIT(31)
>>> +
>>> +#define U2P_R3 0xc
>>> +
>>> +#define RESET_COMPLETE_TIME 500
>>> +
>>> +struct phy_meson_gxl_usb2_priv {
>>> + struct regmap *regmap;
>>> + enum phy_mode mode;
>>> + int is_enabled;
>>> +};
>>> +
>>> +static const struct regmap_config phy_meson_gxl_usb2_regmap_conf = {
>>> + .reg_bits = 8,
>>> + .val_bits = 32,
>>> + .reg_stride = 4,
>>> + .max_register = U2P_R3,
>>> +};
>>> +
>>> +static int phy_meson_gxl_usb2_reset(struct phy *phy)
>>> +{
>>> + struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
>>> +
>>> + if (priv->is_enabled) {
>>> + /* reset the PHY and wait until settings are stabilized */
>>> + regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET,
>>> + U2P_R0_POWER_ON_RESET);
>>> + udelay(RESET_COMPLETE_TIME);
>>> + regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET,
>>> + 0);
>>> + udelay(RESET_COMPLETE_TIME);
>>> + }
>
> Instead of having big if condition blocks, it could be
> if (!priv->is_enabled)
> return 0
>
> the configuration when priv->is_enabled is true should go here.
makes sense (and the code easier to read) in this case - I'll fix it
in the next version
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int phy_meson_gxl_usb2_set_mode(struct phy *phy, enum phy_mode mode)
>>> +{
>>> + struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
>>> +
>>> + switch (mode) {
>>> + case PHY_MODE_USB_HOST:
>>> + case PHY_MODE_USB_OTG:
>>> + regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DM_PULLDOWN,
>>> + U2P_R0_DM_PULLDOWN);
>>> + regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DP_PULLDOWN,
>>> + U2P_R0_DP_PULLDOWN);
>>> + regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_ID_PULLUP, 0);
>>> + break;
>>> +
>>> + case PHY_MODE_USB_DEVICE:
>>> + regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DM_PULLDOWN,
>>> + 0);
>>> + regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DP_PULLDOWN,
>>> + 0);
>>> + regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_ID_PULLUP,
>>> + U2P_R0_ID_PULLUP);
>>> + break;
>>> +
>>> + default:
>>> + return -EINVAL;
>>> + }
>>> +
>>> + phy_meson_gxl_usb2_reset(phy);
>>> +
>>> + priv->mode = mode;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int phy_meson_gxl_usb2_power_off(struct phy *phy)
>>> +{
>>> + struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
>>> +
>>> + priv->is_enabled = 0;
>>> +
>>> + /* power off the PHY by putting it into reset mode */
>>> + regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET,
>>> + U2P_R0_POWER_ON_RESET);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int phy_meson_gxl_usb2_power_on(struct phy *phy)
>>> +{
>>> + struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
>>> + int ret;
>>> +
>>> + priv->is_enabled = 1;
>>> +
>>> + /* power on the PHY by taking it out of reset mode */
>>> + regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET, 0);
>>> +
>>> + ret = phy_meson_gxl_usb2_set_mode(phy, priv->mode);
>
> Since this is already part of phy_ops, the consumer of this phy will take care
> of setting the mode right?
many USB PHYs are configured through of_usb_get_dr_mode_by_phy()
(which fetches the USB controller DT node and looks up the dr_mode
property). this means that the driver will even work for controller
which did not call phy_set_mode() (currently dwc2 and dwc3 are an
example where phy_set_mode() is not called, and this driver is
probably going to be used by both). are you fine with keeping this or
should we instead investigate why dwc2 and dwc3 are not calling
phy_set_mode yet?
>>> + if (ret) {
>>> + phy_meson_gxl_usb2_power_off(phy);
>
> This would mess up the reference count in phy_core, since this function is also
> part of the phy_ops. The consumer should be responsible for powering off the phy.
actually it shouldn't. it would cause issues if I used
phy_power_off(phy) here, but I'm using the driver-internal callback
here.
if phy_meson_gxl_usb2_power_on() fails then phy_power_on() (from
phy-core) prints a warnings and does not increment the internal
ref-counter (++phy->power_count).
so in my opinion there shouldn't be a problem
could you please have a look at my replies for issue #3 and #4 (both
affecting phy_meson_gxl_usb2_power_on) and let me know what you think?
Regards,
Martin
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v3 12/37] mtd: nand: denali: support 1024 byte ECC step size
From: Masahiro Yamada @ 2017-04-01 8:43 UTC (permalink / raw)
To: linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: Enrico Jorns, Artem Bityutskiy, Dinh Nguyen, Boris Brezillon,
Marek Vasut, Graham Moore, David Woodhouse, Masami Hiramatsu,
Chuanxiao Dong, Jassi Brar, Masahiro Yamada,
devicetree-u79uwXL29TY76Z2rM5mHXA, Linux Kernel Mailing List,
Brian Norris, Richard Weinberger, Cyrille Pitchen, Rob Herring,
Mark Rutland
In-Reply-To: <1490856383-31560-13-git-send-email-yamada.masahiro-uWyLwvC0a2jby3iVrkZq2A@public.gmane.org>
2017-03-30 15:45 GMT+09:00 Masahiro Yamada <yamada.masahiro-uWyLwvC0a2jby3iVrkZq2A@public.gmane.org>:
> This driver was originally written for the Intel MRST platform with
> several platform specific parameters hard-coded. Another thing we
> need to fix is the hard-coded ECC step size. Currently, it is
> defined as follows:
>
> #define ECC_SECTOR_SIZE 512
>
> (somehow, it is defined in both denali.c and denali.h)
>
> This must be avoided because the Denali IP supports 1024B ECC size
> as well. The Denali User's Guide also says supporting both 512B and
> 1024B ECC sectors is possible, though it would require instantiation
> of two different ECC circuits. So, possible cases are:
>
> [1] only 512B ECC size is supported
> [2] only 1024B ECC size is supported
> [3] both 512B and 1024B ECC sizes are supported
>
> Newer versions of this IP need ecc.size and ecc.steps explicitly
> set up via the following registers:
> CFG_DATA_BLOCK_SIZE (0x6b0)
> CFG_LAST_DATA_BLOCK_SIZE (0x6c0)
> CFG_NUM_DATA_BLOCKS (0x6d0)
>
> Older versions do not have such registers (they were reserved), so
> write accesses are safely ignored.
>
> This commit adds new flags DENALI_CAP_ECC_SIZE_{512,1024}.
>
> The DT property "nand-ecc-step-size" is still optional; a reasonable
> default will be chosen for [1] and [2]. For case [3], users can
> force ECC size via DT in case firmware hard-codes ECC settings.
> If not specified, the driver will use chip's ECC requirement as a
> hint to decide the ECC size.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro-uWyLwvC0a2jby3iVrkZq2A@public.gmane.org>
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>
> Changes in v3:
> - Move DENALI_CAP_ define out of struct denali_nand_info
> - Use chip->ecc_step_ds as a hint to choose chip->ecc.size
> where possible
>
Please hold back this patch
until we decide how to handle 14.
--
Best Regards
Masahiro Yamada
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] ARM: dts: armada-38x: label USB and SATA nodes
From: Ralph Sennhauser @ 2017-04-01 8:09 UTC (permalink / raw)
To: Andrew Lunn
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Jason Cooper,
Gregory Clement, Sebastian Hesselbarth, Rob Herring, Mark Rutland,
Russell King, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170331182111.GJ22609-g2DYL2Zd6BY@public.gmane.org>
On Fri, 31 Mar 2017 20:21:11 +0200
Andrew Lunn <andrew-g2DYL2Zd6BY@public.gmane.org> wrote:
> On Fri, Mar 31, 2017 at 07:39:20PM +0200, Ralph Sennhauser wrote:
> > On Fri, 31 Mar 2017 18:50:15 +0200
> > Andrew Lunn <andrew-g2DYL2Zd6BY@public.gmane.org> wrote:
> >
> > > > - sata@a8000 {
> > > > + satac0: sata@a8000 {
> > >
> > > Hi Ralph
> > >
> > > Why the c in satac0?
> >
> > For controller and to not conflict with a use case of sata0 for a
> > port, similarly to pciec and pcie1. See
> > armada-385-synology-ds116.dts.
>
> :~/linux/arch/arm/boot/dts$ ls *ds116*
> ls: cannot access '*ds116*': No such file or directory
Ah, not in mainline yet, from linux-next
commit a58d73340b0ec93fc29a826e45fbbfbc3f81b7eb
Author: Willy Tarreau <w@1wt.eu>
Date: Sun Feb 12 10:30:35 2017 +0100
The arch/arm/boot/dts/armada-388-gp.dts from below was
meant as the example for the conflict I mentioned.
>
> But anyway, a few boards seem to solve this by calling the controller
> node ahci0: and the port sata0:
That's another option I missed.
$ git grep -n ahci.:
arch/arm/boot/dts/spear1310.dtsi:59: ahci0: ahci@b1000000 {
arch/arm/boot/dts/spear1310.dtsi:68: ahci1: ahci@b1800000 {
arch/arm/boot/dts/spear1310.dtsi:77: ahci2: ahci@b4000000 {
arch/arm/boot/dts/spear1340.dtsi:42: ahci0: ahci@b1000000 {
Not a big list which I have here and the nodes themselves are named
ahci@xxxxxxxx.
>
> > > > - usb3@f0000 {
> > > > + usb3_0: usb3@f0000 {
> > > > compatible =
> > > > "marvell,armada-380-xhci"; reg = <0xf0000 0x4000>,<0xf4000
> > > > 0x4000>; interrupts = <GIC_SPI 16
> > > > IRQ_TYPE_LEVEL_HIGH>; @@ -598,7 +598,7 @@
> > > > status = "disabled";
> > > > };
> > > >
> > > > - usb3@f8000 {
> > > > + usb3_1: usb3@f8000 {
> > > > compatible =
> > > > "marvell,armada-380-xhci"; reg = <0xf8000 0x4000>,<0xfc000
> > > > 0x4000>; interrupts = <GIC_SPI 17
> > > > IRQ_TYPE_LEVEL_HIGH>;
> > >
> > > I can understand what you are saying. But does anybody else care?
> > > Are there other .dtsi files differentiating between USB 1.1, 2
> > > and 3?
> >
> > It's handled differently where ever I looked, some do some don't. A
> > case for distinguishing USB 2.0 and USB 3.0 like this is
> > armada-388-gp.dts.
>
> Humm...
>
> /* CON4 */
> usb@58000 {
> vcc-supply = <®_usb2_0_vbus>;
> status = "okay";
> };
>
>
> /* CON5 */
> usb3@f0000 {
> usb-phy = <&usb2_1_phy>;
> status = "okay";
> };
>
> /* CON7 */
> usb3@f8000 {
> usb-phy = <&usb3_phy>;
> status = "okay";
> };
>
> Is this clear? Is CON5 a USB 3 host, but has a USB 2 PHY connected to
> it? CON7 is the only true USB 3 port? I think some comments written in
> schwiizerdütsch would be clearre.:-)
Did you just find a bug? :)
*ufm sprung gxi* (about to head out), sorry for the mix-up. The synology
dts would actually have worked for both usb and sata labels :)
$git grep -hn -A8 usb3_0_phy: arch/arm/boot/dts/armada-385-synology-ds116.dts
191: usb3_0_phy: usb3_0_phy {
192- compatible = "usb-nop-xceiv";
193- vcc-supply = <®_usb3_0_vbus>;
194- };
195-
196- usb3_1_phy: usb3_1_phy {
197- compatible = "usb-nop-xceiv";
198- vcc-supply = <®_usb3_1_vbus>;
199- };
---
Let's add another argument for and against usb3_x type labels:
$ git grep -hn usb arch/arm/boot/dts/armada-38x.dtsi
455: usb0: usb@58000 {
593: usb3_0: usb3@f0000 {
601: usb3_1: usb3@f8000 {
They might actually be considered different types. usb vs. usb3, though
that feels quite arbitrary.
$ git grep -hn usb3_0 Documentation/devicetree/bindings/usb/qcom,dwc3.txt
45: usb3_0: usb30@0 {
usb3_0 could be mistaken for the protocol version. A bit of a stretch as well ...
First thought was using usb0,usb1,usb2. For the individual linksys
boards this meant a potential pit-fall, namely using "usb2:" for the
only USB 3.0 port while "usb0:" for the only USB 2.0 port appears in the
armada-385-linksys.dtsi only, hence the quest for alternatives.
In the end it boils down to I couldn't make out a definitive standard and
made a pick that felt about right.
If there was an obvious choice there wouldn't have been a reason to omit
the labels this patch handles when handling the bulk. Make the bulk a none
discussion item and handle the corner cases later. Guess that's what
happened here.
Thanks
Ralph
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC PATCH 2/5] soc/fsl/qbman: Use shared-dma-pool for QMan private memory allocations
From: Scott Wood @ 2017-04-01 7:25 UTC (permalink / raw)
To: Robin Murphy, Michael Ellerman, roy.pledge-3arQi8VN3Tc,
linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: Mark Rutland, madalin.bucur-3arQi8VN3Tc
In-Reply-To: <dfaa1a28-66d8-15fb-7d2d-75e206161770-5wv7dgnIgG8@public.gmane.org>
On Fri, 2017-03-31 at 18:55 +0100, Robin Murphy wrote:
> On 31/03/17 04:27, Michael Ellerman wrote:
> >
> > Robin Murphy <robin.murphy-5wv7dgnIgG8@public.gmane.org> writes:
> >
> > >
> > > Hi Roy,
> > >
> > > On 29/03/17 22:13, Roy Pledge wrote:
> > > >
> > > > Use the shared-memory-pool mechanism for frame queue descriptor and
> > > > packed frame descriptor record area allocations.
> > > Thanks for persevering with this - in my opinion it's now looking like
> > > it was worth the effort :)
> > >
> > > AFAICS the ioremap_wc() that this leads to does appear to give back
> > > something non-cacheable on PPC (assuming "pgprot_noncached_wc" isn't
> > > horrendously misnamed), and "no-map" should rule out any cacheable
> > > linear map alias existing, so it would seem that this approach should
> > > avert Scott's concerns about attribute mismatches.
> > How does 'no-map' translate into something being excluded from the
> > linear mapping?
> Reserved regions marked with "no-map" get memblock_remove()d by
> early_init_dt_alloc_reserved_memory_arch(). As I understand things, the
> linear map should only cover memblock areas, and it would be explicitly
> violating the semantics of "no-map" to still cover such a region.
Discontiguous memory isn't supported on these PPC chips. Everything up to
memblock_end_of_DRAM() gets mapped -- and if that were to change, the
fragmentation would waste TLB1 entries.
This also breaks compatibility with existing device trees. I suggest putting
an ifdef in the qbman driver to add the new scheme for non-PPC arches only.
-Scott
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v3 7/7] ARM: ux500: Add vendor prefix to tps61052 node
From: Javier Martinez Canillas @ 2017-04-01 7:18 UTC (permalink / raw)
To: linux-kernel
Cc: devicetree, Rob Herring, Lee Jones, Javier Martinez Canillas,
Mark Rutland, Russell King, linux-arm-kernel
In-Reply-To: <20170401071854.23198-1-javier@osg.samsung.com>
The tps61052 device node doesn't have a vendor prefix
in its compatible string, fix it by adding one.
Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
---
Changes in v3: None
Changes in v2: None
arch/arm/boot/dts/ste-hrefprev60.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/ste-hrefprev60.dtsi b/arch/arm/boot/dts/ste-hrefprev60.dtsi
index 5882a2606ac3..3f14b4df69b4 100644
--- a/arch/arm/boot/dts/ste-hrefprev60.dtsi
+++ b/arch/arm/boot/dts/ste-hrefprev60.dtsi
@@ -30,7 +30,7 @@
i2c@80004000 {
tps61052@33 {
- compatible = "tps61052";
+ compatible = "ti,tps61052";
reg = <0x33>;
};
--
2.9.3
^ permalink raw reply related
* [PATCH v3 6/7] mfd: tps6105x: Add OF device ID table
From: Javier Martinez Canillas @ 2017-04-01 7:18 UTC (permalink / raw)
To: linux-kernel; +Cc: devicetree, Rob Herring, Lee Jones, Javier Martinez Canillas
In-Reply-To: <20170401071854.23198-1-javier@osg.samsung.com>
The driver doesn't have a struct of_device_id table but supported devices
are registered via Device Trees. This is working on the assumption that a
I2C device registered via OF will always match a legacy I2C device ID and
that the MODALIAS reported will always be of the form i2c:<device>.
But this could change in the future so the correct approach is to have a
OF device ID table if the devices are registered via OF.
Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
---
Changes in v3:
- Add a vendor prefix to the compatible string (Rob Herring).
Changes in v2:
- Don't use of_match_ptr() to avoid build warning when CONFIG_OF is disabled.
drivers/mfd/tps6105x.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c
index baa12ea666fb..187848c93779 100644
--- a/drivers/mfd/tps6105x.c
+++ b/drivers/mfd/tps6105x.c
@@ -173,9 +173,17 @@ static const struct i2c_device_id tps6105x_id[] = {
};
MODULE_DEVICE_TABLE(i2c, tps6105x_id);
+static const struct of_device_id tps6105x_of_match[] = {
+ { .compatible = "ti,tps61050" },
+ { .compatible = "ti,tps61052" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, tps6105x_of_match);
+
static struct i2c_driver tps6105x_driver = {
.driver = {
.name = "tps6105x",
+ .of_match_table = tps6105x_of_match,
},
.probe = tps6105x_probe,
.remove = tps6105x_remove,
--
2.9.3
^ permalink raw reply related
* [PATCH v3 5/7] mfd: Add Device Tree bindings document for TI tps6105x chip
From: Javier Martinez Canillas @ 2017-04-01 7:18 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Lee Jones,
Javier Martinez Canillas, Mark Rutland
In-Reply-To: <20170401071854.23198-1-javier-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
There are Device Tree source files defining a device node for the
tps61050/61052 I2C chip but there isn't a binding document for it.
Signed-off-by: Javier Martinez Canillas <javier-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
---
Changes in v3: None
Changes in v2: None
Documentation/devicetree/bindings/mfd/tps6105x.txt | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mfd/tps6105x.txt
diff --git a/Documentation/devicetree/bindings/mfd/tps6105x.txt b/Documentation/devicetree/bindings/mfd/tps6105x.txt
new file mode 100644
index 000000000000..c076f28575fc
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/tps6105x.txt
@@ -0,0 +1,17 @@
+* Device tree bindings for TI TPS61050/61052 Boost Converters
+
+The TP61050/TPS61052 is a high-power "white LED driver". This boost converter
+is also used for other things than white LEDs, and also contains a GPIO pin.
+
+Required properties:
+- compatible: "ti,tps61050" or "ti,tps61052"
+- reg: Specifies the I2C slave address
+
+Example:
+
+i2c0 {
+ tps61052@33 {
+ compatible = "ti,tps61052";
+ reg = <0x33>;
+ };
+};
--
2.9.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v3 4/7] ARM: dts: n8x0: Add vendor prefix to retu node
From: Javier Martinez Canillas @ 2017-04-01 7:18 UTC (permalink / raw)
To: linux-kernel
Cc: Mark Rutland, devicetree, Tony Lindgren, Russell King,
Javier Martinez Canillas, Rob Herring, Benoît Cousson,
linux-omap, Lee Jones, linux-arm-kernel
In-Reply-To: <20170401071854.23198-1-javier@osg.samsung.com>
The retu-mfd device node doesn't have a vendor prefix
in its compatible string, fix it by adding one.
Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
---
Changes in v3: None
Changes in v2: None
arch/arm/boot/dts/omap2420-n8x0-common.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/omap2420-n8x0-common.dtsi b/arch/arm/boot/dts/omap2420-n8x0-common.dtsi
index 7e5ffc583c90..a633a55820bb 100644
--- a/arch/arm/boot/dts/omap2420-n8x0-common.dtsi
+++ b/arch/arm/boot/dts/omap2420-n8x0-common.dtsi
@@ -16,7 +16,7 @@
#address-cells = <1>;
#size-cells = <0>;
retu_mfd: retu@1 {
- compatible = "retu-mfd";
+ compatible = "nokia,retu-mfd";
interrupt-parent = <&gpio4>;
interrupts = <12 IRQ_TYPE_EDGE_RISING>;
reg = <0x1>;
--
2.9.3
^ permalink raw reply related
* [PATCH v3 3/7] i2c: i2c-cbus-gpio: Add vendor prefix to retu node in example
From: Javier Martinez Canillas @ 2017-04-01 7:18 UTC (permalink / raw)
To: linux-kernel
Cc: devicetree, Rob Herring, Lee Jones, Javier Martinez Canillas,
Wolfram Sang, linux-i2c, Mark Rutland
In-Reply-To: <20170401071854.23198-1-javier@osg.samsung.com>
The example contains a device node for a retu-mfd device,
but its compatible string doesn't have a vendor prefix.
Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
---
Changes in v3: None
Changes in v2: None
Documentation/devicetree/bindings/i2c/i2c-cbus-gpio.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/i2c/i2c-cbus-gpio.txt b/Documentation/devicetree/bindings/i2c/i2c-cbus-gpio.txt
index 8ce9cd2855b5..32bcb1943f00 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-cbus-gpio.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-cbus-gpio.txt
@@ -21,7 +21,7 @@ i2c@0 {
#size-cells = <0>;
retu-mfd: retu@1 {
- compatible = "retu-mfd";
+ compatible = "nokia,retu-mfd";
reg = <0x1>;
};
};
--
2.9.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox