| .. | .. |
|---|
| 138 | 138 | |
|---|
| 139 | 139 | return ret ? : size; |
|---|
| 140 | 140 | } |
|---|
| 141 | + |
|---|
| 142 | +static ssize_t oneshot_repeat_show(struct device *child, |
|---|
| 143 | + struct device_attribute *attr, |
|---|
| 144 | + char *buf) |
|---|
| 145 | +{ |
|---|
| 146 | + const struct pwm_device *pwm = child_to_pwm_device(child); |
|---|
| 147 | + struct pwm_state state; |
|---|
| 148 | + |
|---|
| 149 | + pwm_get_state(pwm, &state); |
|---|
| 150 | + |
|---|
| 151 | + return sprintf(buf, "%u\n", state.oneshot_repeat); |
|---|
| 152 | +} |
|---|
| 153 | + |
|---|
| 154 | +static ssize_t oneshot_repeat_store(struct device *child, |
|---|
| 155 | + struct device_attribute *attr, |
|---|
| 156 | + const char *buf, size_t size) |
|---|
| 157 | +{ |
|---|
| 158 | + struct pwm_export *export = child_to_pwm_export(child); |
|---|
| 159 | + struct pwm_device *pwm = export->pwm; |
|---|
| 160 | + struct pwm_state state; |
|---|
| 161 | + unsigned int val; |
|---|
| 162 | + int ret; |
|---|
| 163 | + |
|---|
| 164 | + ret = kstrtouint(buf, 0, &val); |
|---|
| 165 | + if (ret) |
|---|
| 166 | + return ret; |
|---|
| 167 | + |
|---|
| 168 | + mutex_lock(&export->lock); |
|---|
| 169 | + pwm_get_state(pwm, &state); |
|---|
| 170 | + state.oneshot_repeat = val; |
|---|
| 171 | + ret = pwm_apply_state(pwm, &state); |
|---|
| 172 | + mutex_unlock(&export->lock); |
|---|
| 173 | + |
|---|
| 174 | + return ret ? : size; |
|---|
| 175 | +} |
|---|
| 176 | + |
|---|
| 177 | +static ssize_t duty_offset_show(struct device *child, |
|---|
| 178 | + struct device_attribute *attr, |
|---|
| 179 | + char *buf) |
|---|
| 180 | +{ |
|---|
| 181 | + const struct pwm_device *pwm = child_to_pwm_device(child); |
|---|
| 182 | + struct pwm_state state; |
|---|
| 183 | + |
|---|
| 184 | + pwm_get_state(pwm, &state); |
|---|
| 185 | + |
|---|
| 186 | + return sprintf(buf, "%llu\n", state.duty_offset); |
|---|
| 187 | +} |
|---|
| 188 | + |
|---|
| 189 | +static ssize_t duty_offset_store(struct device *child, |
|---|
| 190 | + struct device_attribute *attr, |
|---|
| 191 | + const char *buf, size_t size) |
|---|
| 192 | +{ |
|---|
| 193 | + struct pwm_export *export = child_to_pwm_export(child); |
|---|
| 194 | + struct pwm_device *pwm = export->pwm; |
|---|
| 195 | + struct pwm_state state; |
|---|
| 196 | + u64 val; |
|---|
| 197 | + int ret; |
|---|
| 198 | + |
|---|
| 199 | + ret = kstrtou64(buf, 0, &val); |
|---|
| 200 | + if (ret) |
|---|
| 201 | + return ret; |
|---|
| 202 | + |
|---|
| 203 | + mutex_lock(&export->lock); |
|---|
| 204 | + pwm_get_state(pwm, &state); |
|---|
| 205 | + state.duty_offset = val; |
|---|
| 206 | + ret = pwm_apply_state(pwm, &state); |
|---|
| 207 | + mutex_unlock(&export->lock); |
|---|
| 208 | + |
|---|
| 209 | + return ret ? : size; |
|---|
| 210 | +} |
|---|
| 141 | 211 | #endif |
|---|
| 142 | 212 | |
|---|
| 143 | 213 | static ssize_t enable_show(struct device *child, |
|---|
| .. | .. |
|---|
| 279 | 349 | static DEVICE_ATTR_RW(duty_cycle); |
|---|
| 280 | 350 | #ifdef CONFIG_PWM_ROCKCHIP_ONESHOT |
|---|
| 281 | 351 | static DEVICE_ATTR_RW(oneshot_count); |
|---|
| 352 | +static DEVICE_ATTR_RW(oneshot_repeat); |
|---|
| 353 | +static DEVICE_ATTR_RW(duty_offset); |
|---|
| 282 | 354 | #endif |
|---|
| 283 | 355 | static DEVICE_ATTR_RW(enable); |
|---|
| 284 | 356 | static DEVICE_ATTR_RW(polarity); |
|---|
| .. | .. |
|---|
| 290 | 362 | &dev_attr_duty_cycle.attr, |
|---|
| 291 | 363 | #ifdef CONFIG_PWM_ROCKCHIP_ONESHOT |
|---|
| 292 | 364 | &dev_attr_oneshot_count.attr, |
|---|
| 365 | + &dev_attr_oneshot_repeat.attr, |
|---|
| 366 | + &dev_attr_duty_offset.attr, |
|---|
| 293 | 367 | #endif |
|---|
| 294 | 368 | &dev_attr_enable.attr, |
|---|
| 295 | 369 | &dev_attr_polarity.attr, |
|---|
| .. | .. |
|---|
| 492 | 566 | if (!export) |
|---|
| 493 | 567 | continue; |
|---|
| 494 | 568 | |
|---|
| 569 | + /* If pwmchip was not enabled before suspend, do nothing. */ |
|---|
| 570 | + if (!export->suspend.enabled) { |
|---|
| 571 | + /* release lock taken in pwm_class_get_state */ |
|---|
| 572 | + mutex_unlock(&export->lock); |
|---|
| 573 | + continue; |
|---|
| 574 | + } |
|---|
| 575 | + |
|---|
| 495 | 576 | state.enabled = export->suspend.enabled; |
|---|
| 496 | 577 | ret = pwm_class_apply_state(export, pwm, &state); |
|---|
| 497 | 578 | if (ret < 0) |
|---|
| .. | .. |
|---|
| 516 | 597 | if (!export) |
|---|
| 517 | 598 | continue; |
|---|
| 518 | 599 | |
|---|
| 600 | + /* |
|---|
| 601 | + * If pwmchip was not enabled before suspend, save |
|---|
| 602 | + * state for resume time and do nothing else. |
|---|
| 603 | + */ |
|---|
| 519 | 604 | export->suspend = state; |
|---|
| 605 | + if (!state.enabled) { |
|---|
| 606 | + /* release lock taken in pwm_class_get_state */ |
|---|
| 607 | + mutex_unlock(&export->lock); |
|---|
| 608 | + continue; |
|---|
| 609 | + } |
|---|
| 610 | + |
|---|
| 520 | 611 | state.enabled = false; |
|---|
| 521 | 612 | ret = pwm_class_apply_state(export, pwm, &state); |
|---|
| 522 | 613 | if (ret < 0) { |
|---|