pm8921: Add pwm driver for pmic.

Change-Id: I7846754945b21399c77ae58d6c09843ca8aa07f2
diff --git a/dev/pmic/pm8921/include/dev/pm8921_pwm.h b/dev/pmic/pm8921/include/dev/pm8921_pwm.h
new file mode 100755
index 0000000..8f2f34d
--- /dev/null
+++ b/dev/pmic/pm8921/include/dev/pm8921_pwm.h
@@ -0,0 +1,166 @@
+/*
+ * * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution.
+ *  * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PMIC_PWM_H
+#define __PMIC_PWM_H
+
+/* PMIC 8921 LPG defines */
+
+#define PM8921_LPG_CTL_BASE         (0x13C)
+
+#define PM8921_LPG_CTL(n)           (PM8921_LPG_CTL_BASE + (n))
+#define PM8921_LPG_BANK_SEL         (0x143)
+#define PM8921_LPG_BANK_ENABLE      (0x144)
+
+#define USEC_PER_SEC                1000000L
+#define NSEC_PER_SEC                1000000000L
+#define NSEC_PER_USEC               1000
+
+#define PWM_FREQ_HZ                 300
+#define PWM_LEVEL                   15
+
+#define NUM_CLOCKS                  3
+#define NUM_PRE_DIVIDE              4
+
+#define NUM_LPG_CTL_REGS            7
+
+#define PRE_DIVIDE_0                2
+#define PRE_DIVIDE_1                3
+#define PRE_DIVIDE_2                5
+#define PRE_DIVIDE_3                6
+
+#define PRE_DIVIDE_MIN              PRE_DIVIDE_0
+#define PRE_DIVIDE_MAX              PRE_DIVIDE_3
+
+#define PM_PWM_M_MIN                0
+#define PM_PWM_M_MAX                7
+
+#define NSEC_1000HZ                (NSEC_PER_SEC / 1000)
+#define NSEC_32768HZ               (NSEC_PER_SEC / 32768)
+#define NSEC_19P2MHZ               (NSEC_PER_SEC / 19200000)
+
+#define CLK_PERIOD_MIN             NSEC_19P2MHZ
+#define CLK_PERIOD_MAX             NSEC_1000HZ
+
+#define MIN_MPT                    ((PRE_DIVIDE_MIN * CLK_PERIOD_MIN) << PM_PWM_M_MIN)
+#define MAX_MPT                    ((PRE_DIVIDE_MAX * CLK_PERIOD_MAX) << PM_PWM_M_MAX)
+
+/* The MAX value is computation limit. Hardware limit is 393 seconds. */
+#define PM_PWM_PERIOD_MAX          (274 * USEC_PER_SEC)
+/* The MIN value is hardware limit. */
+#define PM_PWM_PERIOD_MIN          7 /* micro seconds */
+
+#define PWM_PERIOD_USEC           (USEC_PER_SEC / PWM_FREQ_HZ)
+#define PWM_DUTY_LEVEL            (PWM_PERIOD_USEC / PWM_LEVEL)
+
+/* Control 0 */
+#define PM_PWM_1KHZ_COUNT_MASK    0xF0
+#define PM_PWM_1KHZ_COUNT_SHIFT   4
+
+#define PM_PWM_1KHZ_COUNT_MAX     15
+
+#define PM_PWM_OUTPUT_EN          0x08
+#define PM_PWM_PWM_EN             0x04
+#define PM_PWM_RAMP_GEN_EN        0x02
+#define PM_PWM_RAMP_START         0x01
+
+#define PM_PWM_PWM_START          (PM_PWM_OUTPUT_EN | PM_PWM_PWM_EN)
+#define PM_PWM_RAMP_GEN_START     (PM_PWM_RAMP_GEN_EN | PM_PWM_RAMP_START)
+
+/* Control 1 */
+#define PM_PWM_REVERSE_EN         0x80
+#define PM_PWM_BYPASS_LUT         0x40
+#define PM_PWM_HIGH_INDEX_MASK    0x3F
+
+/* Control 2 */
+#define PM_PWM_LOOP_EN            0x80
+#define PM_PWM_RAMP_UP            0x40
+#define PM_PWM_LOW_INDEX_MASK     0x3F
+
+/* Control 3 */
+#define PM_PWM_VALUE_BIT7_0       0xFF
+#define PM_PWM_VALUE_BIT5_0       0x3F
+
+/* Control 4 */
+#define PM_PWM_VALUE_BIT8         0x80
+
+#define PM_PWM_CLK_SEL_MASK       0x60
+#define PM_PWM_CLK_SEL_SHIFT      5
+
+#define PM_PWM_CLK_SEL_NO         0
+#define PM_PWM_CLK_SEL_1KHZ       1
+#define PM_PWM_CLK_SEL_32KHZ      2
+#define PM_PWM_CLK_SEL_19P2MHZ    3
+
+#define PM_PWM_PREDIVIDE_MASK     0x18
+#define PM_PWM_PREDIVIDE_SHIFT    3
+
+#define PM_PWM_PREDIVIDE_2        0
+#define PM_PWM_PREDIVIDE_3        1
+#define PM_PWM_PREDIVIDE_5        2
+#define PM_PWM_PREDIVIDE_6        3
+
+#define PM_PWM_M_MASK             0x07
+#define PM_PWM_M_MIN              0
+#define PM_PWM_M_MAX              7
+
+/* Control 5 */
+#define PM_PWM_PAUSE_COUNT_HI_MASK    0xFC
+#define PM_PWM_PAUSE_COUNT_HI_SHIFT   2
+
+#define PM_PWM_PAUSE_ENABLE_HIGH      0x02
+#define PM_PWM_SIZE_9_BIT             0x01
+
+/* Control 6 */
+#define PM_PWM_PAUSE_COUNT_LO_MASK    0xFC
+#define PM_PWM_PAUSE_COUNT_LO_SHIFT   2
+
+#define PM_PWM_PAUSE_ENABLE_LOW       0x02
+#define PM_PWM_RESERVED               0x01
+
+#define PM_PWM_PAUSE_COUNT_MAX        56 /* < 2^6 = 64*/
+
+struct pm_pwm_config {
+    uint8_t pwm_size;      /* round up to 6 or 9 for 6/9-bit PWM SIZE */
+    uint8_t clk;
+    uint8_t pre_div;
+    uint8_t pre_div_exp;
+    uint8_t pwm_value;
+    uint8_t bypass_lut;
+    uint8_t pwm_ctl[NUM_LPG_CTL_REGS];
+};
+
+/* External PWM functions */
+int pm8921_pwm_enable(uint8_t pwm_id, pm8921_dev_t *dev);
+int pm8921_pwm_config(uint8_t pwm_id,
+    uint32_t duty_us,
+    uint32_t period_us,
+    pm8921_dev_t *dev);
+
+#endif