cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pwm-ab8500.c (3349B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) ST-Ericsson SA 2010
      4 *
      5 * Author: Arun R Murthy <arun.murthy@stericsson.com>
      6 */
      7#include <linux/err.h>
      8#include <linux/platform_device.h>
      9#include <linux/slab.h>
     10#include <linux/pwm.h>
     11#include <linux/mfd/abx500.h>
     12#include <linux/mfd/abx500/ab8500.h>
     13#include <linux/module.h>
     14
     15/*
     16 * PWM Out generators
     17 * Bank: 0x10
     18 */
     19#define AB8500_PWM_OUT_CTRL1_REG	0x60
     20#define AB8500_PWM_OUT_CTRL2_REG	0x61
     21#define AB8500_PWM_OUT_CTRL7_REG	0x66
     22
     23struct ab8500_pwm_chip {
     24	struct pwm_chip chip;
     25	unsigned int hwid;
     26};
     27
     28static struct ab8500_pwm_chip *ab8500_pwm_from_chip(struct pwm_chip *chip)
     29{
     30	return container_of(chip, struct ab8500_pwm_chip, chip);
     31}
     32
     33static int ab8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
     34			    const struct pwm_state *state)
     35{
     36	int ret;
     37	u8 reg;
     38	unsigned int higher_val, lower_val;
     39	struct ab8500_pwm_chip *ab8500 = ab8500_pwm_from_chip(chip);
     40
     41	if (state->polarity != PWM_POLARITY_NORMAL)
     42		return -EINVAL;
     43
     44	if (!state->enabled) {
     45		ret = abx500_mask_and_set_register_interruptible(chip->dev,
     46					AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
     47					1 << ab8500->hwid, 0);
     48
     49		if (ret < 0)
     50			dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
     51								pwm->label, ret);
     52		return ret;
     53	}
     54
     55	/*
     56	 * get the first 8 bits that are be written to
     57	 * AB8500_PWM_OUT_CTRL1_REG[0:7]
     58	 */
     59	lower_val = state->duty_cycle & 0x00FF;
     60	/*
     61	 * get bits [9:10] that are to be written to
     62	 * AB8500_PWM_OUT_CTRL2_REG[0:1]
     63	 */
     64	higher_val = ((state->duty_cycle & 0x0300) >> 8);
     65
     66	reg = AB8500_PWM_OUT_CTRL1_REG + (ab8500->hwid * 2);
     67
     68	ret = abx500_set_register_interruptible(chip->dev, AB8500_MISC,
     69			reg, (u8)lower_val);
     70	if (ret < 0)
     71		return ret;
     72
     73	ret = abx500_set_register_interruptible(chip->dev, AB8500_MISC,
     74			(reg + 1), (u8)higher_val);
     75	if (ret < 0)
     76		return ret;
     77
     78	ret = abx500_mask_and_set_register_interruptible(chip->dev,
     79				AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
     80				1 << ab8500->hwid, 1 << ab8500->hwid);
     81	if (ret < 0)
     82		dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n",
     83							pwm->label, ret);
     84
     85	return ret;
     86}
     87
     88static const struct pwm_ops ab8500_pwm_ops = {
     89	.apply = ab8500_pwm_apply,
     90	.owner = THIS_MODULE,
     91};
     92
     93static int ab8500_pwm_probe(struct platform_device *pdev)
     94{
     95	struct ab8500_pwm_chip *ab8500;
     96	int err;
     97
     98	if (pdev->id < 1 || pdev->id > 31)
     99		return dev_err_probe(&pdev->dev, EINVAL, "Invalid device id %d\n", pdev->id);
    100
    101	/*
    102	 * Nothing to be done in probe, this is required to get the
    103	 * device which is required for ab8500 read and write
    104	 */
    105	ab8500 = devm_kzalloc(&pdev->dev, sizeof(*ab8500), GFP_KERNEL);
    106	if (ab8500 == NULL)
    107		return -ENOMEM;
    108
    109	ab8500->chip.dev = &pdev->dev;
    110	ab8500->chip.ops = &ab8500_pwm_ops;
    111	ab8500->chip.npwm = 1;
    112	ab8500->hwid = pdev->id - 1;
    113
    114	err = devm_pwmchip_add(&pdev->dev, &ab8500->chip);
    115	if (err < 0)
    116		return dev_err_probe(&pdev->dev, err, "Failed to add pwm chip\n");
    117
    118	dev_dbg(&pdev->dev, "pwm probe successful\n");
    119
    120	return 0;
    121}
    122
    123static struct platform_driver ab8500_pwm_driver = {
    124	.driver = {
    125		.name = "ab8500-pwm",
    126	},
    127	.probe = ab8500_pwm_probe,
    128};
    129module_platform_driver(ab8500_pwm_driver);
    130
    131MODULE_AUTHOR("Arun MURTHY <arun.murthy@stericsson.com>");
    132MODULE_DESCRIPTION("AB8500 Pulse Width Modulation Driver");
    133MODULE_ALIAS("platform:ab8500-pwm");
    134MODULE_LICENSE("GPL v2");