Changes between Initial Version and Version 1 of linux/pwm


Ignore:
Timestamp:
10/22/2017 05:28:45 AM (7 years ago)
Author:
trac
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • linux/pwm

    v1 v1  
     1[[PageOutline]]
     2
     3= Pulse Width Modulation (PWM) =
     4Pulse Width Modulation refers to a modulation technique where a digital output signal will alternate high and low with possibly differing on/off times. PWM signals are commonly used in embedded systems for:
     5 * controlling analog devices (by using an RC circuit to convert the digital PWM signal to an analog voltage)
     6 * controlling the brightness of an LED
     7 * controlling the position of an RC hobby stepper motor
     8
     9When working with PWM's the following terminology is commonly used:
     10 * period - represents the period the PWM signal alternates between its off/on times
     11 * duty-cycle - represents the on time as a percentage of the duty cycle (ie 10% duty-cycle means the signal is on for 10% of the period and off for 90% of the period)
     12
     13Many Gateworks boards have on-board PWM controllers and offer one or more PWM outputs with 3.3V TTL voltage levels.
     14
     15References:
     16 - https://en.wikipedia.org/wiki/Pulse-width_modulation
     17
     18
     19[=#hardware-mapping]
     20= PWM mapping =
     21The various product hardware manuals will call out what PWM devices are available on each board.
     22
     23The hardware mapping of the PWM controllers is defined in the Linux kernel device-tree for Ventana (ie http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi).
     24
     25If debugfs is enabled in the kernel (as it is on Gateworks BSP's) you can see a nice table of PWM mapping via {{{/sys/kernel/debug/pwm}}} showing each PWM controller by name, a list of the PWM's it provides, what driver (if any) has control over them, and their state. For example:
     26{{{
     27#!bash
     28root@ventana:~# cat /sys/kernel/debug/pwm
     29platform/208c000.pwm, 1 PWM device
     30 pwm-0   (backlight           ): requested enabled
     31
     32platform/2088000.pwm, 1 PWM device
     33 pwm-0   ((null)              ):
     34
     35platform/2084000.pwm, 1 PWM device
     36 pwm-0   (sysfs               ): requested enabled
     37
     38platform/2080000.pwm, 1 PWM device
     39 pwm-0   ((null)              ):
     40}}}
     41 * The above is an IMX6 showing its 4 controllers available, each controller providing 1 PWM pin. The first one shown (0x208c000 maps to IMX PWM4) is used by the backlight driver. The 2nd (0x2088000 maps to IMX PWM3) is unused. The third one (0x2084000 maps to IMX PWM2) is exported for use by sysfs. The fourth (0x2080000 maps to IMX PWM1) is unused.
     42
     43== Ventana PWM mapping ==
     44The IMX6 SoC has 4 PWM controllers each having a single PWM signal:
     45||= IMX6 controller address =||= IMX6 pwm =||
     46|| pwm@02080000 || pwm1 ||
     47|| pwm@02084000 || pwm2 ||
     48|| pwm@02088000 || pwm3 ||
     49|| pwm@0208c000 || pwm4 ||
     50
     51Only the controllers enabled in the device-tree will be registered therefore you won't always see pwmchip0-3 and can't depend on that mapping to be consistent as it varies board to board and is also dependent on which (if any) DIO's you may have configured as PWM via the bootloader {{{hwconfig}}} variable. You must look at the symlink /sys/class/pwm/pwmchip*/device to see what controller is linked to.
     52
     53The Ventana bootloader {{{hwconfig}}} env variable must be properly set to configure PWM mode for the DIO pin, otherwise the pin will be muxed to the GPIO controller and the pwmchip controller will be disabled. For example, to configure DIO1 as a PWM and DIO0, DIO2, DIO3 as GPIO:
     54{{{
     55#!bash
     56Ventana> setenv hwconfig 'dio0:mode=gpio;dio1:mode=pwm;dio2:mode=gpio;dio3:mode=gpio'
     57Ventana> saveenv
     58}}}
     59
     60For example a GW53xx which has DIO1 configured as a GPIO, and DIO2 configured as a PWM (PWM3) shows:
     61 * bootloader {{{hwconfig}}}
     62{{{
     63#!bash
     64root@ventana:~# fw_printenv | grep hwconfig
     65hwconfig=dio0:mode=gpio;dio1:mode=pwm;dio2:mode=gpio;dio3:mode=gpio
     66}}}
     67 * /sys/kernel/debug/pwm:
     68{{{
     69#!bash
     70root@ventana:~# cat /sys/kernel/debug/pwm
     71platform/208c000.pwm, 1 PWM device
     72 pwm-0   (backlight           ): requested enabled
     73
     74platform/2088000.pwm, 1 PWM device
     75 pwm-0   ((null)              ):
     76
     77platform/2080000.pwm, 1 PWM device
     78 pwm-0   ((null)              ):
     79}}}
     80 * /sys/class/pwmchip* linkage:
     81{{{
     82#!bash
     83root@ventana:~# ls -l /sys/class/pwm/pwmchip*/device
     84lrwxrwxrwx    1 root     root             0 Dec 18 15:33 /sys/class/pwm/pwmchip0/device -> ../../../2080000.pwm
     85lrwxrwxrwx    1 root     root             0 Dec 18 15:33 /sys/class/pwm/pwmchip1/device -> ../../../2088000.pwm
     86lrwxrwxrwx    1 root     root             0 Dec 18 15:33 /sys/class/pwm/pwmchip2/device -> ../../../208c000.pwm
     87}}}
     88  - shows that IMX6 pwm1 is /sys/class/pwm/pwmchip0 (because its linked to the controller address 0x2080000). This is unused but it is present because its controller's node was not specifically 'disabled' in the device-tree.
     89  - shows that IMX6 pwm3 is /sys/class/pwm/pwmchip1 (because its linked to the controller address 0x2088000). This is PWM3 which on the GW53xx is mapped to DIO2 coming out J4.3. This is present because the bootloader {{{hwconfig}}} specified DIO2 as a PWM.
     90  - shows that IMX6 pwm4 is /sys/class/pwm/pwmchip2 (because its linked to the controller address 0x208c000). This is PWM4 which on the GW53xx is mapped to the backlight controller present on the LVDS connector.
     91
     92
     93You can use the following script will provide the sysfs path for an IMX PWM:
     94{{{
     95#!bash
     96#!/bin/sh
     97
     98# match IMX PWM{$1} with available pwm controllers
     99for i in $(ls /sys/class/pwm); do
     100        link=$(readlink /sys/class/pwm/$i)
     101        IMXPWM=
     102        case "$link" in
     103                *2080000*) IMXPWM=1;;
     104                *2084000*) IMXPWM=2;;
     105                *2088000*) IMXPWM=3;;
     106                *208c000*) IMXPWM=4;;
     107        esac
     108        [ $IMXPWM -a $IMXPWM == $1 ] && { chip=$i; break; }
     109done
     110[ $chip ] || { echo "chip not found for IMX PWM$1"; exit; }
     111
     112path="/sys/class/pwm/$chip"
     113
     114# export first pwm for chip
     115echo "$path/pwm0"
     116[ -d $path/pwm0 ] || { echo 0 > $path/export; }
     117[ -d $path/pwm0 ] || { echo "Export failed - not PWM$1 not available"; }
     118}}}
     119
     120Example use:
     121{{{
     122#!bash
     123root@ventana:/ # /data/test 2 # get path for IMX PWM2
     124/sys/class/pwm/pwmchip1/pwm0
     125}}}
     126
     127The following table shows what PWM's are available on the various Ventana baseboards:
     128||= '''Board'''  =||= '''DIO''',,(1),,  =||= '''Connector''',,(2),, =||= '''IMX6_PAD''',,(3),, =||= '''IMX6 GPIO''',,(4),, =||= '''linux gpio''',,(5),, =||= '''linux PWM''',,(6),, =||
     129|| GW51xx         || DIO1 || J11.7     || PAD_SD1_DATA2 || GPIO1_IO19 || gpio-19 || PWM2 (0x02084000) ||
     130|| GW51xx         || DIO2 || J11.6     || PAD_SD1_DATA1 || GPIO1_IO17 || gpio-17 || PWM3 (0x02088000) ||
     131|| GW51xx         || DIO3 || J11.8     || PAD_SD1_CMD   || GPIO1_IO18 || gpio-18 || PWM4 (0x0208C000) ||
     132|| ||
     133|| GW52xx         || DIO1 || J4.2      || PAD_SD1_DATA2 || GPIO1_IO19 || gpio-19 || PWM2 (0x02084000) ||
     134|| GW52xx         || DIO2 || J4.3      || PAD_SD1_DATA1 || GPIO1_IO17 || gpio-17 || PWM3 (0x02088000) ||
     135|| GW52xx         || -    || J6.5      || PAD_SD1_CMD   || GPIO1_IO18 || gpio-18 || PWM4 (0x0208C000) ||
     136|| ||
     137|| GW53xx         || DIO1 || J4.2      || PAD_SD1_DATA2 || GPIO1_IO19 || gpio-19 || PWM2 (0x02084000) ||
     138|| GW53xx         || DIO2 || J4.3      || PAD_SD1_DATA1 || GPIO1_IO17 || gpio-17 || PWM3 (0x02088000) ||
     139|| GW53xx         || -    || J6.5      || PAD_SD1_CMD   || GPIO1_IO18 || gpio-18 || PWM4 (0x0208C000) ||
     140|| ||
     141|| GW54xx         || DIO0 || J16.1     || PAD_GPIO_9    || GPIO1_IO09 || gpio-9  || PWM1 (0x02080000) ||
     142|| GW54xx         || DIO1 || J16.2     || PAD_SD1_DATA2 || GPIO1_IO19 || gpio-19 || PWM2 (0x02084000) ||
     143|| GW54xx         || DIO2 || J16.3     || PAD_SD4_DATA1 || GPIO2_IO09 || gpio-41 || PWM3 (0x02088000) ||
     144|| GW54xx         || DIO3,,(7),, || J16.4     || PAD_SD4_DATA2 || GPIO2_IO10 || gpio-42 || PWM4 (0x0208C000) ||
     145|| GW54xx         || -    || J6.5      || PAD_SD1_CMD   || GPIO1_IO18 || gpio-18 || PWM4 (0x0208C000) ||
     146|| ||
     147|| GW553x         || DIO1 || J10.7     || PAD_SD1_DATA2 || GPIO1_IO19 || gpio-19 || PWM2 (0x02084000) ||
     148|| GW553x         || DIO2 || J10.6     || PAD_SD1_DATA1 || GPIO1_IO17 || gpio-17 || PWM3 (0x02088000) ||
     149|| GW53xx         || DIO3 || J10.8     || PAD_SD1_CMD   || GPIO1_IO18 || gpio-18 || PWM4 (0x0208C000) ||
     150|| ||
     151|| GW552x         || DIO1 || J8.11     || PAD_SD1_DATA2 || GPIO1_IO19 || gpio-19 || PWM2 (0x02084000) ||
     152|| GW552x         || DIO2 || J8.10     || PAD_SD1_DATA1 || GPIO1_IO17 || gpio-17 || PWM3 (0x02088000) ||
     153|| ||
     154|| GW551x         || DIO1 || J3.19     || PAD_SD1_DATA2 || GPIO1_IO19 || gpio-19 || PWM2 (0x02084000) ||
     155|| GW551x         || DIO2 || J3.20     || PAD_SD1_DATA1 || GPIO2_IO17 || gpio-17 || PWM3 (0x02088000) ||
     156||
     157
     158 1. This is the signal name from the [http://www.gateworks.com/usermanuals Ventana hardware manuals]
     159 2. This is the connector pinout.  The 5th pin on 5-pin connectors is GND
     160 3. Consult the IMX6 Reference manuals for PAD info: [http://cache.freescale.com/files/32bit/doc/ref_manual/IMX6DQRM.pdf IMX6DQRM] [http://cache.freescale.com/files/32bit/doc/ref_manual/IMX6SDLRM.pdf IMX6SDLRM]
     161 4. This is the GPIO block and IO the PAD is pinmux'd to when hwconfig is configured for GPIO
     162 5. This is the gpio mapped in linux accessible via /sys/class/gpio.  Note that the pinmux and IO configuration are done by the [wiki:ventana/bootloader#DIOconfiguration bootloader], but you will need to manually export the GPIO to use it (see [wiki:gpio here] for details)
     163 6. This is the PWM that the PAD is pinmux'd to by the bootloader with hwconfig is conifgured for PWM. [wiki:ventana/bootloader#DIOconfiguration u-boot hwconfig to configure DIO pinmux/config]
     164 7. The GW5400 PWM4 can be routed to two different pads/connectors. By default the Ventana kernel device-tree's map PWM4 to the J6.5 backlight connector. If you want to use PWM4 as DIO3 on J16.4 you need to change the kernel device-tree and should contact support@gateworks.com for details.
     165
     166See also:
     167 * [wiki:ventana/DigitalIO Ventana Digital IO Mapping Page]
     168 * [http://www.gateworks.com/usermanuals Board specific hardware manual]
     169
     170
     171[=#linux]
     172= Linux PWM and pwm class =
     173The Linux kernel con provide pwm functionality to userspace via a pwm class accessed via sysfs (/sys/class/pwm/). For userspace access this requires sysfs kernel support (CONFIG_SYSFS) and the sysfs filesystem mounted which is standard for most linux systems including Gateworks BSP's). This framework allows boards to define PWM controllers and allow userspace to make use of them by adjusting their period, duty-cycle, and enable.
     174
     175Note that any pwm that is registered for use by a driver is not available for exporting for userspace control. You can {{{cat /sys/kernel/debug/pwm}}} to see what pwm's are currently registered with the kernel (those shown to be owned by {{{sysfs}}} are exported for userspace, those shown as {{{null}}} are not exported or in use by any driver).
     176
     177Note that the pwm sysfs API is slightly different from the gpio sysfs API:
     178 * the individual pwm's from a pwmchip (controller) are in the subdir of the pwmchip and all start with index 0 (whereas gpio's are exported to /sys/class/gpio and keep increasing in number)
     179
     180Each exported pwm will be in the sub-directory of it's controller chip and will be 0 based. For example, the 2nd pwm of a pwm controller that has 16 pwm's which was the 3rd pwm controller to be registered will be /sys/class/pwmchip2/pwm1 (0 based).
     181
     182You can determine which pwmchip is which by either looking at {{{/sys/kernel/debug/pwm}}} or the symlink of the device file in the pwmchip directory.
     183
     184Here are some example use cases for using pwm-class via syfs:
     185 * to see pwm names and state: (requires debugfs kernel support and fs mounted)
     186{{{
     187#!bash
     188cat /sys/kernel/debug/pwm
     189}}}
     190 * to export a PWM that is not currently in use:
     191{{{
     192#!bash
     193echo 0 > /sys/class/pwm/pwmchip0/export # export the first pwm (pwm0) on the first pwm controller (pwmchip0)
     194}}}
     195 * to change the period of the PWM signal (value is in nanoseconds and is the sum of the active and inactive time of the PWM)
     196{{{
     197#!bash
     198echo 1000000 > /sys/class/pwm/pwmchip0/pwm0/period # set 1ms period
     199cat /sys/class/pwm/pwmchip0/pwm0/period # see period
     200}}}
     201 * to change the duty cycle of the PWM signal (value is in nanoseconds refers to the time the signal is active and must be less than the period)
     202{{{
     203#!bash
     204echo 500000 > /sys/class/pwm/pwmchip0/pwm0/period # set 500us (50% duty-cycle if period is 1ms)
     205cat /sys/class/pwm/pwmchip0/pwm0/duty_cycle # see duty_cycle
     206}}}
     207 * to change the polarity of the PWM signal: (*Note not supported on i.MX6 PWM)
     208{{{
     209#!bash
     210echo normal > /sys/class/pwm/pwmchip0/pwm0/polarity # set normal polarity
     211echo inversed > /sys/class/pwm/pwmchip0/pwm0/polarity # set inverted polarity
     212cat /sys/class/pwm/pwmchip0/pwm0/polarity # see polarity
     213}}}
     214 * to enable/disable a PWM signal:
     215{{{
     216#!bash
     217echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable # enable output
     218echo 0 > /sys/class/pwm/pwmchip0/pwm0/enable # disable output
     219}}}
     220
     221References:
     222 - [http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/pwm.txt Documentation/pwm.txt]
     223
     224= PWM based LEDs =
     225See wiki:linux/led
     226
     227= PWM based Backlight =
     228See wiki:linux/backlight