Re: [RFC PATCH v2] checkpatch: add shebang check to EXECUTE_PERMISSIONS
On Wed, 2020-10-14 at 08:47 +0200, Lukas Bulwahn wrote: > > On Tue, 13 Oct 2020, Joe Perches wrote: > > > On Wed, 2020-10-14 at 08:36 +0200, Lukas Bulwahn wrote: > > > On Tue, 13 Oct 2020, Joe Perches wrote: > > > > > > > On Wed, 2020-10-14 at 08:21 +0200, Lukas Bulwahn wrote: > > > > > What does checkpatch.pl warn about and what does clang-format still > > > > > warn > > > > > about, which is generally accepted okay as style in the kernel? > > > > > > > > clang-format doesn't warn at all, it just reformats. > > > > > > > You can run clang-format with --dry-run and then it would just state the > > > proposed changes, right? > > > > clang-format through at least version 10 does not have > > a --dry-run option. > > > > > > Just a quick check: > > version 9 does not have the --dry-run option: > > https://releases.llvm.org/9.0.0/tools/clang/docs/ClangFormat.html > > version 10 does: > > https://releases.llvm.org/10.0.0/tools/clang/docs/ClangFormat.html Perhaps some version 10 variants do, but 10.0.0 does not. $ which clang-format /usr/local/bin/clang-format $ clang-format --version clang-format version 10.0.0 (git://github.com/llvm/llvm-project.git 305b961f64b75e73110e309341535f6d5a48ed72) $ clang-format --dry-run clang-format: Unknown command line argument '--dry-run'. Try: 'clang-format --help' clang-format: Did you mean ' --debug'?
[PATCH 2/2] jffs2: fix can't set rp_size to zero during remounting
From: lizhe Set rp_size to zero will be ignore during remounting. The method to identify whether we input a remounting option of rp_size is to check if the rp_size input is zero. It can not work well if we pass "rp_size=0". This patch add a bool variable "set_rp_size" to fix this problem. By the way, the problem of NULL pointer dereference in rp_size fs option parsing showed at https://lore.kernel.org/linux-mtd/20201012131204.59102-1-ja...@nuviainc.com/T/#u should be applyed before this patch to make sure it works well. Reported-by: Jubin Zhong Signed-off-by: lizhe --- fs/jffs2/jffs2_fs_sb.h | 1 + fs/jffs2/super.c | 7 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h index 778275f48a87..5a7091746f68 100644 --- a/fs/jffs2/jffs2_fs_sb.h +++ b/fs/jffs2/jffs2_fs_sb.h @@ -38,6 +38,7 @@ struct jffs2_mount_opts { * users. This is implemented simply by means of not allowing the * latter users to write to the file system if the amount if the * available space is less then 'rp_size'. */ + bool set_rp_size; unsigned int rp_size; }; diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 4fd297bdf0f3..c523adaca79f 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -88,7 +88,7 @@ static int jffs2_show_options(struct seq_file *s, struct dentry *root) if (opts->override_compr) seq_printf(s, ",compr=%s", jffs2_compr_name(opts->compr)); - if (opts->rp_size) + if (opts->set_rp_size) seq_printf(s, ",rp_size=%u", opts->rp_size / 1024); return 0; @@ -206,6 +206,7 @@ static int jffs2_parse_param(struct fs_context *fc, struct fs_parameter *param) if (opt > c->mtd->size) return invalf(fc, "jffs2: Too large reserve pool specified, max is %llu KB", c->mtd->size / 1024); + c->mount_opts.set_rp_size = true; c->mount_opts.rp_size = opt; break; default: @@ -225,8 +226,10 @@ static inline void jffs2_update_mount_opts(struct fs_context *fc) c->mount_opts.override_compr = new_c->mount_opts.override_compr; c->mount_opts.compr = new_c->mount_opts.compr; } - if (new_c->mount_opts.rp_size) + if (new_c->mount_opts.set_rp_size) { + c->mount_opts.set_rp_size = new_c->mount_opts.set_rp_size; c->mount_opts.rp_size = new_c->mount_opts.rp_size; + } mutex_unlock(&c->alloc_sem); } -- 2.12.3
[PATCH 1/2] jffs2: fix ignoring mounting options problem during remounting
From: lizhe The jffs2 mount options will be ignored when remounting jffs2. It can be easily reproduced with the steps listed below. 1. mount -t jffs2 -o compr=none /dev/mtdblockx /mnt 2. mount -o remount compr=zlib /mnt Since ec10a24f10c8, the option parsing happens before fill_super and then pass fc, which contains the options parsing results, to function jffs2_reconfigure during remounting. But function jffs2_reconfigure do not update c->mount_opts. This patch add a function jffs2_update_mount_opts to fix this problem. By the way, I notice that tmpfs use the same way to update remounting options. If it is necessary to unify them? Signed-off-by: lizhe --- fs/jffs2/super.c | 17 + 1 file changed, 17 insertions(+) diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 05d7878dfad1..4fd297bdf0f3 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -215,11 +215,28 @@ static int jffs2_parse_param(struct fs_context *fc, struct fs_parameter *param) return 0; } +static inline void jffs2_update_mount_opts(struct fs_context *fc) +{ + struct jffs2_sb_info *new_c = fc->s_fs_info; + struct jffs2_sb_info *c = JFFS2_SB_INFO(fc->root->d_sb); + + mutex_lock(&c->alloc_sem); + if (new_c->mount_opts.override_compr) { + c->mount_opts.override_compr = new_c->mount_opts.override_compr; + c->mount_opts.compr = new_c->mount_opts.compr; + } + if (new_c->mount_opts.rp_size) + c->mount_opts.rp_size = new_c->mount_opts.rp_size; + mutex_unlock(&c->alloc_sem); +} + static int jffs2_reconfigure(struct fs_context *fc) { struct super_block *sb = fc->root->d_sb; sync_filesystem(sb); + jffs2_update_mount_opts(fc); + return jffs2_do_remount_fs(sb, fc); } -- 2.12.3
Re: [PATCH 5.8 050/124] drm/vmwgfx: Fix error handling in get_node
On Tue, Oct 13, 2020 at 05:55:31PM +0200, Roland Scheidegger wrote: > Hi, > > this commit should NOT be applied to 5.8. > It fixes a regression introduced by > 58e4d686d456c3e356439ae160ff4a0728940b8e (drm/ttm: cleanup > ttm_mem_type_manager_func.get_node interface v3) which is part of 5.9 > but not 5.8. > Applying this to 5.8 will very likely break things. I don't know why it > ended up as a candidate for 5.8. Now dropped, thanks. And it was probably picked up due to the wording in the changelog text, along with a lack of a "Fixes:" tag that pointed at the exact change it fixed up, which would have shown that this is a 5.9-only thing. thanks, greg k-h
Re: [PATCH v3 2/2] vhost-vdpa: fix page pinning leakage in error path
On Tue, Oct 13, 2020 at 04:42:59PM -0700, si-wei liu wrote: > > On 10/9/2020 7:27 PM, Jason Wang wrote: > > > > On 2020/10/3 下午1:02, Si-Wei Liu wrote: > > > Pinned pages are not properly accounted particularly when > > > mapping error occurs on IOTLB update. Clean up dangling > > > pinned pages for the error path. As the inflight pinned > > > pages, specifically for memory region that strides across > > > multiple chunks, would need more than one free page for > > > book keeping and accounting. For simplicity, pin pages > > > for all memory in the IOVA range in one go rather than > > > have multiple pin_user_pages calls to make up the entire > > > region. This way it's easier to track and account the > > > pages already mapped, particularly for clean-up in the > > > error path. > > > > > > Fixes: 4c8cf31885f6 ("vhost: introduce vDPA-based backend") > > > Signed-off-by: Si-Wei Liu > > > --- > > > Changes in v3: > > > - Factor out vhost_vdpa_map() change to a separate patch > > > > > > Changes in v2: > > > - Fix incorrect target SHA1 referenced > > > > > > drivers/vhost/vdpa.c | 119 > > > ++- > > > 1 file changed, 71 insertions(+), 48 deletions(-) > > > > > > diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c > > > index 0f27919..dad41dae 100644 > > > --- a/drivers/vhost/vdpa.c > > > +++ b/drivers/vhost/vdpa.c > > > @@ -595,21 +595,19 @@ static int > > > vhost_vdpa_process_iotlb_update(struct vhost_vdpa *v, > > > struct vhost_dev *dev = &v->vdev; > > > struct vhost_iotlb *iotlb = dev->iotlb; > > > struct page **page_list; > > > -unsigned long list_size = PAGE_SIZE / sizeof(struct page *); > > > +struct vm_area_struct **vmas; > > > unsigned int gup_flags = FOLL_LONGTERM; > > > -unsigned long npages, cur_base, map_pfn, last_pfn = 0; > > > -unsigned long locked, lock_limit, pinned, i; > > > +unsigned long map_pfn, last_pfn = 0; > > > +unsigned long npages, lock_limit; > > > +unsigned long i, nmap = 0; > > > u64 iova = msg->iova; > > > +long pinned; > > > int ret = 0; > > > if (vhost_iotlb_itree_first(iotlb, msg->iova, > > > msg->iova + msg->size - 1)) > > > return -EEXIST; > > > -page_list = (struct page **) __get_free_page(GFP_KERNEL); > > > -if (!page_list) > > > -return -ENOMEM; > > > - > > > if (msg->perm & VHOST_ACCESS_WO) > > > gup_flags |= FOLL_WRITE; > > > @@ -617,61 +615,86 @@ static int > > > vhost_vdpa_process_iotlb_update(struct vhost_vdpa *v, > > > if (!npages) > > > return -EINVAL; > > > +page_list = kvmalloc_array(npages, sizeof(struct page *), > > > GFP_KERNEL); > > > +vmas = kvmalloc_array(npages, sizeof(struct vm_area_struct *), > > > + GFP_KERNEL); > > > > > > This will result high order memory allocation which was what the code > > tried to avoid originally. > > > > Using an unlimited size will cause a lot of side effects consider VM or > > userspace may try to pin several TB of memory. > Hmmm, that's a good point. Indeed, if the guest memory demand is huge or the > host system is running short of free pages, kvmalloc will be problematic and > less efficient than the __get_free_page implementation. OK so ... Jason, what's the plan? How about you send a patchset with 1. revert this change 2. fix error handling leak > > > > > > > +if (!page_list || !vmas) { > > > +ret = -ENOMEM; > > > +goto free; > > > +} > > > > > > Any reason that you want to use vmas? > Without providing custom vmas, it's subject to high order allocation > failure. While page_list and vmas can now fallback to virtual memory > allocation if need be. > > > > > > > > + > > > mmap_read_lock(dev->mm); > > > -locked = atomic64_add_return(npages, &dev->mm->pinned_vm); > > > lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; > > > - > > > -if (locked > lock_limit) { > > > +if (npages + atomic64_read(&dev->mm->pinned_vm) > lock_limit) { > > > ret = -ENOMEM; > > > -goto out; > > > +goto unlock; > > > } > > > -cur_base = msg->uaddr & PAGE_MASK; > > > -iova &= PAGE_MASK; > > > +pinned = pin_user_pages(msg->uaddr & PAGE_MASK, npages, gup_flags, > > > +page_list, vmas); > > > +if (npages != pinned) { > > > +if (pinned < 0) { > > > +ret = pinned; > > > +} else { > > > +unpin_user_pages(page_list, pinned); > > > +ret = -ENOMEM; > > > +} > > > +goto unlock; > > > +} > > > -while (npages) { > > > -pinned = min_t(unsigned long, npages, list_size); > > > -ret = pin_user_pages(cur_base, pinned, > > > - gup_flags, page_list, NULL); > > > -if (ret != pinned) > > > -goto out; > > > - > > > -if (!last_pfn) > > > -map_pfn =
Re: [RFC PATCH v2] checkpatch: add shebang check to EXECUTE_PERMISSIONS
On Wed, 2020-10-14 at 08:36 +0200, Lukas Bulwahn wrote: > > On Tue, 13 Oct 2020, Joe Perches wrote: > > > On Wed, 2020-10-14 at 08:21 +0200, Lukas Bulwahn wrote: > > > What does checkpatch.pl warn about and what does clang-format still warn > > > about, which is generally accepted okay as style in the kernel? > > > > clang-format doesn't warn at all, it just reformats. > > > You can run clang-format with --dry-run and then it would just state the > proposed changes, right? clang-format through at least version 10 does not have a --dry-run option.
Re: [PATCH] arm64/mm: Validate hotplug range before creating linear mapping
On Wed, 14 Oct 2020 at 07:07, Anshuman Khandual wrote: > > > > On 10/12/2020 12:59 PM, Ard Biesheuvel wrote: > > On Tue, 6 Oct 2020 at 08:36, Anshuman Khandual > > wrote: > >> > >> > >> > >> On 09/30/2020 01:32 PM, Anshuman Khandual wrote: > >>> But if __is_lm_address() checks against the effective linear range instead > >>> i.e [_PAGE_OFFSET(vabits_actual)..(PAGE_END - 1)], it can be used for hot > >>> plug physical range check there after. Perhaps something like this, though > >>> not tested properly. > >>> > >>> diff --git a/arch/arm64/include/asm/memory.h > >>> b/arch/arm64/include/asm/memory.h > >>> index afa722504bfd..6da046b479d4 100644 > >>> --- a/arch/arm64/include/asm/memory.h > >>> +++ b/arch/arm64/include/asm/memory.h > >>> @@ -238,7 +238,10 @@ static inline const void *__tag_set(const void > >>> *addr, u8 tag) > >>> * space. Testing the top bit for the start of the region is a > >>> * sufficient check and avoids having to worry about the tag. > >>> */ > >>> -#define __is_lm_address(addr) (!(((u64)addr) & BIT(vabits_actual - 1))) > >>> +static inline bool __is_lm_address(unsigned long addr) > >>> +{ > >>> + return ((addr >= _PAGE_OFFSET(vabits_actual)) && (addr <= > >>> (PAGE_END - 1))); > >>> +} > >>> > >>> #define __lm_to_phys(addr) (((addr) + physvirt_offset)) > >>> #define __kimg_to_phys(addr) ((addr) - kimage_voffset) > >>> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c > >>> index d59ffabb9c84..5750370a7e8c 100644 > >>> --- a/arch/arm64/mm/mmu.c > >>> +++ b/arch/arm64/mm/mmu.c > >>> @@ -1451,8 +1451,7 @@ static bool inside_linear_region(u64 start, u64 > >>> size) > >>> * address range mapped by the linear map, the start address > >>> should > >>> * be calculated using vabits_actual. > >>> */ > >>> - return ((start >= __pa(_PAGE_OFFSET(vabits_actual))) > >>> - && ((start + size) <= __pa(PAGE_END - 1))); > >>> + return __is_lm_address(__va(start)) && __is_lm_address(__va(start > >>> + size)); > >>> } > >>> > >>> int arch_add_memory(int nid, u64 start, u64 size, > >> > >> Will/Ard, > >> > >> Any thoughts about this ? __is_lm_address() now checks for a range instead > >> of a bit. This will be compatible later on, even if linear mapping range > >> changes from current lower half scheme. > >> > > > > As I'm sure you have noticed, I sent out some patches that get rid of > > physvirt_offset, and which simplify __is_lm_address() to only take > > compile time constants into account (unless KASAN is enabled). This > > means that in the 52-bit VA case, __is_lm_address() does not > > distinguish between virtual addresses that can be mapped by the > > hardware and ones that cannot. > > Yeah, though was bit late in getting to the series. So with that change > there might be areas in the linear mapping which cannot be addressed by > the hardware and hence should also need be checked apart from proposed > linear mapping coverage test, during memory hotplug ? > Yes. > > > > In the memory hotplug case, we need to decide whether the added memory > > will appear in the addressable area, which is a different question. So > > it makes sense to duplicate some of the logic that exists in > > arm64_memblock_init() (or factor it out) to decide whether this newly > > added memory will appear in the addressable window or not. > > It seems unlikely that any hotplug agent (e.g. firmware) will ever push > through a memory range which is not accessible in the hardware but then > it is not impossible either. In summary, arch_add_memory() should check > > 1. Range can be covered inside linear mapping > 2. Range is accessible by the hardware > > Before the VA space organization series, (2) was not necessary as it was > contained inside (1) ? > Not really. We have a problem with KASLR randomization of the linear region, which may choose memstart_addr in such a way that we lose access to regions that are beyond the boot time value of memblock_end_of_DRAM(). I think we should probably rework that code to take ID_AA64MMFR0_EL1.PARange into account instead. > > > > So I think your original approach makes more sense here, although I > > think you want '(start + size - 1) <= __pa(PAGE_END - 1)' in the > > comparison above (and please drop the redundant parens) > > > > Sure, will accommodate these changes.
Re: [RFC PATCH v2] checkpatch: add shebang check to EXECUTE_PERMISSIONS
On Wed, 2020-10-14 at 08:21 +0200, Lukas Bulwahn wrote: > What does checkpatch.pl warn about and what does clang-format still warn > about, which is generally accepted okay as style in the kernel? clang-format doesn't warn at all, it just reformats. checkpatch using the --in-place can reformat a patch or file with an explanation of each change it makes.
[PATCH v2 10/17] ASoC: sun8i-codec: Automatically set the system sample rate
The sun8i codec has three clock/sample rate domains: - The AIF1 domain, with a sample rate equal to AIF1 LRCK - The AIF2 domain, with a sample rate equal to AIF2 LRCK - The SYSCLK domain, containing the ADC, DAC, and effects (AGC/DRC), with a sample rate given by a divisor from SYSCLK. The divisor is controlled by the AIF1_FS or AIF2_FS field in SYS_SR_CTRL, depending on if SYSCLK's source is AIF1CLK or AIF2CLK, respectively. The exact sample rate depends on if SYSCLK is running at 22.6 MHz or 24.6 MHz. When an AIF (currently only AIF1) is active, the ADC and DAC should run at that sample rate to avoid artifacting. Sample rate conversion is only available when multiple AIFs are active and are routed to each other; this means the sample rate conversion hardware usually cannot be used. Only attach the event hook to the channel 0 AIF widgets, since we only need one event when a DAI stream starts or stops. Channel 0 is always brought up with a DAI stream, regardless of the number of channels in the stream. The ADC and DAC (along with their effects blocks) can be used even if no AIFs are in use. In that case, we should select an appropriate sample rate divisor, instead of keeping the last-used AIF sample rate. 44.1/48 kHz was chosen to balance audio quality and power consumption. Since the sample rate is tied to active AIF paths, disabling pmdown_time allows switching to the optimal sample rate immediately, instead of after a 5 second delay. Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun8i-codec.c | 103 +++--- 1 file changed, 84 insertions(+), 19 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 38349d85fb17..468fa5f71bd3 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -89,31 +89,36 @@ #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12) #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8) #define SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV_MASK GENMASK(14, 13) #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK GENMASK(12, 9) #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK GENMASK(8, 6) #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK GENMASK(5, 4) #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK GENMASK(3, 2) +#define SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE 48000 + #define SUN8I_CODEC_PCM_RATES (SNDRV_PCM_RATE_8000_48000|\ SNDRV_PCM_RATE_88200 |\ SNDRV_PCM_RATE_96000 |\ SNDRV_PCM_RATE_176400|\ SNDRV_PCM_RATE_192000|\ SNDRV_PCM_RATE_KNOT) enum { SUN8I_CODEC_AIF1, SUN8I_CODEC_NAIFS }; struct sun8i_codec_aif { + unsigned intsample_rate; unsigned intslots; unsigned intslot_width; + unsigned intactive_streams : 2; + unsigned intopen_streams: 2; }; struct sun8i_codec_quirks { bool legacy_widgets : 1; bool lrck_inversion : 1; }; struct sun8i_codec { @@ -144,21 +149,19 @@ static int sun8i_codec_runtime_suspend(struct device *dev) struct sun8i_codec *scodec = dev_get_drvdata(dev); regcache_cache_only(scodec->regmap, true); regcache_mark_dirty(scodec->regmap); return 0; } -static int sun8i_codec_get_hw_rate(struct snd_pcm_hw_params *params) +static int sun8i_codec_get_hw_rate(unsigned int sample_rate) { - unsigned int rate = params_rate(params); - - switch (rate) { + switch (sample_rate) { case 7350: case 8000: return 0x0; case 11025: return 0x1; case 12000: return 0x2; case 14700: @@ -181,16 +184,43 @@ static int sun8i_codec_get_hw_rate(struct snd_pcm_hw_params *params) case 176400: case 192000: return 0xa; default: return -EINVAL; } } +static int sun8i_codec_update_sample_rate(struct sun8i_codec *scodec) +{ + unsigned int max_rate = 0; + int hw_rate, i; + + for (i = SUN8I_CODEC_AIF1; i < SUN8I_CODEC_NAIFS; ++i) { + struct sun8i_codec_aif *aif = &scodec->aifs[i]; + + if (aif->active_streams) + max_rate = max(max_rate, aif->sample_rate); + } + + /* Set the sample rate for ADC->DAC passthrough when no AIF is active. */ + if (!max_rate) + max_rate = SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE; + + hw_rate = sun8i_codec_get_hw_rate(max_rate); + if (hw_rate < 0) + return hw_rate; + + regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL, + SUN8I_SYS_SR_CTRL_AIF1_FS_MASK, + hw_rate << SUN8I_SYS_SR_CTRL_AIF1_FS); + + return 0; +} + static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) {
[PATCH v2 13/17] ASoC: sun8i-codec: Require an exact BCLK divisor match
Now that we guarantee that SYSCLK is running at the optimal rate when hw_params succeeds, and that it will continue running at that rate, SYSCLK will always be an integer multiple of BCLK. So we can always pick the exact divider, not just the closest divider. Acked-by: Maxime Ripard Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun8i-codec.c | 22 ++ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 253857e66f6f..a530e58018b7 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -384,35 +384,31 @@ static const struct sun8i_codec_clk_div sun8i_codec_bclk_div[] = { { .div = 32,.val = 8 }, { .div = 48,.val = 9 }, { .div = 64,.val = 10 }, { .div = 96,.val = 11 }, { .div = 128, .val = 12 }, { .div = 192, .val = 13 }, }; -static u8 sun8i_codec_get_bclk_div(unsigned int sysclk_rate, - unsigned int lrck_div_order, - unsigned int sample_rate) +static int sun8i_codec_get_bclk_div(unsigned int sysclk_rate, + unsigned int lrck_div_order, + unsigned int sample_rate) { unsigned int div = sysclk_rate / sample_rate >> lrck_div_order; - unsigned int best_val = 0, best_diff = ~0; int i; for (i = 0; i < ARRAY_SIZE(sun8i_codec_bclk_div); i++) { const struct sun8i_codec_clk_div *bdiv = &sun8i_codec_bclk_div[i]; - unsigned int diff = abs(bdiv->div - div); - if (diff < best_diff) { - best_diff = diff; - best_val = bdiv->val; - } + if (bdiv->div == div) + return bdiv->val; } - return best_val; + return -EINVAL; } static int sun8i_codec_get_lrck_div_order(unsigned int slots, unsigned int slot_width) { unsigned int div = slots * slot_width; if (div < 16 || div > 256) @@ -431,18 +427,17 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); struct sun8i_codec_aif *aif = &scodec->aifs[dai->id]; unsigned int sample_rate = params_rate(params); unsigned int slots = aif->slots ?: params_channels(params); unsigned int slot_width = aif->slot_width ?: params_width(params); unsigned int sysclk_rate = sun8i_codec_get_sysclk_rate(sample_rate); - int lrck_div_order, ret, word_size; - u8 bclk_div; + int bclk_div, lrck_div_order, ret, word_size; /* word size */ switch (params_width(params)) { case 8: word_size = 0x0; break; case 16: word_size = 0x1; @@ -467,16 +462,19 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, return lrck_div_order; regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK, (lrck_div_order - 4) << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV); /* BCLK divider (SYSCLK/BCLK ratio) */ bclk_div = sun8i_codec_get_bclk_div(sysclk_rate, lrck_div_order, sample_rate); + if (bclk_div < 0) + return bclk_div; + regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK, bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV); /* * SYSCLK rate * * Clock rate protection is reference counted; but hw_params may be -- 2.26.2
[PATCH v2 14/17] ASoC: sun8i-codec: Enable all supported PCM formats
Now that the DAI clock setup is correct for all hardware-supported PCM formats, we can enable them in the driver. With the appropriate support in the CPU DAI driver, this allows userspace to access the additional formats. Since this codec is connected to the CPU via a DAI, not directly, we do not care if the CPU DAI is using 3-byte or 4-byte formats, so we can support them both. Acked-by: Maxime Ripard Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun8i-codec.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index a530e58018b7..e3abf8363d9b 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -91,16 +91,23 @@ #define SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV_MASK GENMASK(14, 13) #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK GENMASK(12, 9) #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK GENMASK(8, 6) #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK GENMASK(5, 4) #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK GENMASK(3, 2) #define SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE 48000 +#define SUN8I_CODEC_PCM_FORMATS(SNDRV_PCM_FMTBIT_S8 |\ +SNDRV_PCM_FMTBIT_S16_LE |\ +SNDRV_PCM_FMTBIT_S20_LE |\ +SNDRV_PCM_FMTBIT_S24_LE |\ +SNDRV_PCM_FMTBIT_S20_3LE|\ +SNDRV_PCM_FMTBIT_S24_3LE) + #define SUN8I_CODEC_PCM_RATES (SNDRV_PCM_RATE_8000_48000|\ SNDRV_PCM_RATE_88200 |\ SNDRV_PCM_RATE_96000 |\ SNDRV_PCM_RATE_176400|\ SNDRV_PCM_RATE_192000|\ SNDRV_PCM_RATE_KNOT) enum { @@ -535,26 +542,26 @@ static struct snd_soc_dai_driver sun8i_codec_dais[] = { .id = SUN8I_CODEC_AIF1, .ops= &sun8i_codec_dai_ops, /* capture capabilities */ .capture = { .stream_name= "AIF1 Capture", .channels_min = 1, .channels_max = 2, .rates = SUN8I_CODEC_PCM_RATES, - .formats= SNDRV_PCM_FMTBIT_S16_LE, + .formats= SUN8I_CODEC_PCM_FORMATS, .sig_bits = 24, }, /* playback capabilities */ .playback = { .stream_name= "AIF1 Playback", .channels_min = 1, .channels_max = 2, .rates = SUN8I_CODEC_PCM_RATES, - .formats= SNDRV_PCM_FMTBIT_S16_LE, + .formats= SUN8I_CODEC_PCM_FORMATS, }, .symmetric_rates= true, .symmetric_channels = true, .symmetric_samplebits = true, }, }; static int sun8i_codec_aif_event(struct snd_soc_dapm_widget *w, -- 2.26.2
Re: [f2fs-dev] [PATCH v3] f2fs: handle errors of f2fs_get_meta_page_nofail be failed
On 2020/10/13 11:07, jaeg...@kernel.org wrote: First problem is we hit BUG_ON() in f2fs_get_sum_page given EIO on f2fs_get_meta_page_nofail(). Quick fix was not to give any error with infinite loop, but syzbot caught a case where it goes to that loop from fuzzed image. In turned out we abused f2fs_get_meta_page_nofail() like in the below call stack. - f2fs_fill_super - f2fs_build_segment_manager - build_sit_entries - get_current_sit_page INFO: task syz-executor178:6870 can't die for more than 143 seconds. task:syz-executor178 state:R stack:26960 pid: 6870 ppid: 6869 flags:0x4006 Call Trace: Showing all locks held in the system: 1 lock held by khungtaskd/1179: #0: 8a554da0 (rcu_read_lock){}-{1:2}, at: debug_show_all_locks+0x53/0x260 kernel/locking/lockdep.c:6242 1 lock held by systemd-journal/3920: 1 lock held by in:imklog/6769: #0: 88809eebc130 (&f->f_pos_lock){+.+.}-{3:3}, at: __fdget_pos+0xe9/0x100 fs/file.c:930 1 lock held by syz-executor178/6870: #0: 8880925120e0 (&type->s_umount_key#47/1){+.+.}-{3:3}, at: alloc_super+0x201/0xaf0 fs/super.c:229 Actually, we didn't have to use _nofail in this case, since we could return error to mount(2) already with the error handler. As a result, this patch tries to 1) remove _nofail callers as much as possible, 2) deal with error case in last remaining caller, f2fs_get_sum_page(). Reported-by: syzbot+ee250ac8137be41d7...@syzkaller.appspotmail.com Signed-off-by: Jaegeuk Kim I prefer to use f2fs_get_meta_page() as much as possible except change_curseg() path, however, it's minor, and the time is closing to merge window, so: Reviewed-by: Chao Yu Thanks, --- Change log from v2: - avoid _nofail and add error handler fs/f2fs/checkpoint.c | 2 +- fs/f2fs/f2fs.h | 2 +- fs/f2fs/node.c | 2 +- fs/f2fs/segment.c| 12 +--- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index f18386d30f031..023462e80e58d 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -107,7 +107,7 @@ struct page *f2fs_get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index) return __get_meta_page(sbi, index, true); } -struct page *f2fs_get_meta_page_nofail(struct f2fs_sb_info *sbi, pgoff_t index) +struct page *f2fs_get_meta_page_retry(struct f2fs_sb_info *sbi, pgoff_t index) { struct page *page; int count = 0; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index ae46d44bd5211..adda53d20a399 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3422,7 +3422,7 @@ unsigned int f2fs_usable_blks_in_seg(struct f2fs_sb_info *sbi, void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io); struct page *f2fs_grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index); struct page *f2fs_get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index); -struct page *f2fs_get_meta_page_nofail(struct f2fs_sb_info *sbi, pgoff_t index); +struct page *f2fs_get_meta_page_retry(struct f2fs_sb_info *sbi, pgoff_t index); struct page *f2fs_get_tmp_page(struct f2fs_sb_info *sbi, pgoff_t index); bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi, block_t blkaddr, int type); diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 93fb34d636eb5..d5d8ce077f295 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -109,7 +109,7 @@ static void clear_node_page_dirty(struct page *page) static struct page *get_current_nat_page(struct f2fs_sb_info *sbi, nid_t nid) { - return f2fs_get_meta_page_nofail(sbi, current_nat_addr(sbi, nid)); + return f2fs_get_meta_page(sbi, current_nat_addr(sbi, nid)); } static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 13ecd2c2c361b..05ab5ae2b5f7f 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2379,7 +2379,9 @@ int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra) */ struct page *f2fs_get_sum_page(struct f2fs_sb_info *sbi, unsigned int segno) { - return f2fs_get_meta_page_nofail(sbi, GET_SUM_BLOCK(sbi, segno)); + if (unlikely(f2fs_cp_error(sbi))) + return ERR_PTR(-EIO); + return f2fs_get_meta_page_retry(sbi, GET_SUM_BLOCK(sbi, segno)); } void f2fs_update_meta_page(struct f2fs_sb_info *sbi, @@ -2669,7 +2671,11 @@ static void change_curseg(struct f2fs_sb_info *sbi, int type, bool flush) __next_free_blkoff(sbi, curseg, 0); sum_page = f2fs_get_sum_page(sbi, new_segno); - f2fs_bug_on(sbi, IS_ERR(sum_page)); + if (IS_ERR(sum_page)) { + /* GC won't be able to use stale summary pages by cp_error */ + memset(curseg->sum_blk, 0, SUM_ENTRY_SIZE); + return; + } sum_node = (struct f2fs_summary_block *)page_address(sum_page); memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE); f2fs_put_page(sum_page, 1); @@ -3
[PATCH v2 12/17] ASoC: sun8i-codec: Protect the clock rate while streams are open
The codec's clock input is shared among all AIFs, and shared with other audio-related hardware in the SoC, including I2S and SPDIF controllers. To ensure sample rates selected by userspace or by codec2codec DAI links are maintained, the clock rate must be protected while it is in use. Signed-off-by: Samuel Holland --- sound/soc/sunxi/Kconfig | 1 + sound/soc/sunxi/sun8i-codec.c | 29 +++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig index 9cd7009cb570..69b9d8515335 100644 --- a/sound/soc/sunxi/Kconfig +++ b/sound/soc/sunxi/Kconfig @@ -9,16 +9,17 @@ config SND_SUN4I_CODEC help Select Y or M to add support for the Codec embedded in the Allwinner A10 and affiliated SoCs. config SND_SUN8I_CODEC tristate "Allwinner SUN8I audio codec" depends on OF depends on MACH_SUN8I || (ARM64 && ARCH_SUNXI) || COMPILE_TEST + select COMMON_CLK select REGMAP_MMIO help This option enables the digital part of the internal audio codec for Allwinner sun8i SoC (and particularly A33). Say Y or M if you want to add sun8i digital audio codec support. config SND_SUN8I_CODEC_ANALOG diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 0e8b0ac31fed..253857e66f6f 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -416,27 +416,32 @@ static int sun8i_codec_get_lrck_div_order(unsigned int slots, unsigned int div = slots * slot_width; if (div < 16 || div > 256) return -EINVAL; return order_base_2(div); } +static unsigned int sun8i_codec_get_sysclk_rate(unsigned int sample_rate) +{ + return sample_rate % 4000 ? 22579200 : 24576000; +} + static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); struct sun8i_codec_aif *aif = &scodec->aifs[dai->id]; unsigned int sample_rate = params_rate(params); unsigned int slots = aif->slots ?: params_channels(params); unsigned int slot_width = aif->slot_width ?: params_width(params); - unsigned int sysclk_rate = clk_get_rate(scodec->clk_module); - int lrck_div_order, word_size; + unsigned int sysclk_rate = sun8i_codec_get_sysclk_rate(sample_rate); + int lrck_div_order, ret, word_size; u8 bclk_div; /* word size */ switch (params_width(params)) { case 8: word_size = 0x0; break; case 16: @@ -466,35 +471,55 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, (lrck_div_order - 4) << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV); /* BCLK divider (SYSCLK/BCLK ratio) */ bclk_div = sun8i_codec_get_bclk_div(sysclk_rate, lrck_div_order, sample_rate); regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK, bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV); + /* +* SYSCLK rate +* +* Clock rate protection is reference counted; but hw_params may be +* called many times per substream, without matching calls to hw_free. +* Protect the clock rate once per AIF, on the first hw_params call +* for the first substream. clk_set_rate() will allow clock rate +* changes on subsequent calls if only one AIF has open streams. +*/ + ret = (aif->open_streams ? clk_set_rate : clk_set_rate_exclusive)(scodec->clk_module, + sysclk_rate); + if (ret == -EBUSY) + dev_err(dai->dev, + "%s sample rate (%u Hz) conflicts with other audio streams\n", + dai->name, sample_rate); + if (ret < 0) + return ret; + if (!aif->open_streams) scodec->sysclk_refcnt++; scodec->sysclk_rate = sysclk_rate; aif->sample_rate = sample_rate; aif->open_streams |= BIT(substream->stream); return sun8i_codec_update_sample_rate(scodec); } static int sun8i_codec_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); struct sun8i_codec_aif *aif = &scodec->aifs[dai->id]; + /* Drop references when the last substream for the AIF is freed. */ if (aif->open_streams != BIT(substream->stream)) goto done; + clk_rate_exclusive_put(scodec->clk_module); scodec->sysclk_refcnt--; aif->sample_rate = 0; done:
[PATCH] [PATCH] [v3] wireless: Initial driver submission for pureLiFi STA devices
This introduces the pureLiFi LiFi driver for LiFi-X, LiFi-XC and LiFi-XL USB devices. This driver implementation has been based on the zd1211rw driver. Driver is based on 802.11 softMAC Architecture and uses native 802.11 for configuration and management The driver is compiled and tested in ARM, x86 architectures and compiled in powerpc architecture Signed-off-by: Srinivasan Raju --- MAINTAINERS|5 + drivers/net/wireless/Kconfig |1 + drivers/net/wireless/Makefile |1 + drivers/net/wireless/purelifi/Kconfig | 27 + drivers/net/wireless/purelifi/Makefile |3 + drivers/net/wireless/purelifi/chip.c | 97 ++ drivers/net/wireless/purelifi/chip.h | 82 ++ drivers/net/wireless/purelifi/intf.h | 38 + drivers/net/wireless/purelifi/mac.c| 874 + drivers/net/wireless/purelifi/mac.h| 178 +++ drivers/net/wireless/purelifi/usb.c| 1647 drivers/net/wireless/purelifi/usb.h| 147 +++ 12 files changed, 3100 insertions(+) create mode 100644 drivers/net/wireless/purelifi/Kconfig create mode 100644 drivers/net/wireless/purelifi/Makefile create mode 100644 drivers/net/wireless/purelifi/chip.c create mode 100644 drivers/net/wireless/purelifi/chip.h create mode 100644 drivers/net/wireless/purelifi/intf.h create mode 100644 drivers/net/wireless/purelifi/mac.c create mode 100644 drivers/net/wireless/purelifi/mac.h create mode 100644 drivers/net/wireless/purelifi/usb.c create mode 100644 drivers/net/wireless/purelifi/usb.h diff --git a/MAINTAINERS b/MAINTAINERS index c80f87d7258c..150f592fb6e4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14108,6 +14108,11 @@ T: git git://linuxtv.org/media_tree.git F: Documentation/admin-guide/media/pulse8-cec.rst F: drivers/media/cec/usb/pulse8/ +PUREILIFI USB DRIVER +M: Srinivasan Raju +S: Maintained +F: drivers/net/wireless/purelifi + PVRUSB2 VIDEO4LINUX DRIVER M: Mike Isely L: pvru...@isely.net (subscribers-only) diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 170a64e67709..b87da3139f94 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -48,6 +48,7 @@ source "drivers/net/wireless/st/Kconfig" source "drivers/net/wireless/ti/Kconfig" source "drivers/net/wireless/zydas/Kconfig" source "drivers/net/wireless/quantenna/Kconfig" +source "drivers/net/wireless/purelifi/Kconfig" config PCMCIA_RAYCS tristate "Aviator/Raytheon 2.4GHz wireless support" diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 80b324499786..e9fc770026f0 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_WLAN_VENDOR_ST) += st/ obj-$(CONFIG_WLAN_VENDOR_TI) += ti/ obj-$(CONFIG_WLAN_VENDOR_ZYDAS) += zydas/ obj-$(CONFIG_WLAN_VENDOR_QUANTENNA) += quantenna/ +obj-$(CONFIG_WLAN_VENDOR_PURELIFI) += purelifi/ # 16-bit wireless PCMCIA client drivers obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o diff --git a/drivers/net/wireless/purelifi/Kconfig b/drivers/net/wireless/purelifi/Kconfig new file mode 100644 index ..f6630791df9d --- /dev/null +++ b/drivers/net/wireless/purelifi/Kconfig @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0 +config WLAN_VENDOR_PURELIFI + bool "pureLiFi devices" + default y + help + If you have a pureLiFi device, say Y. + + Note that the answer to this question doesn't directly affect the + kernel: saying N will just cause the configurator to skip all the + questions about these cards. If you say Y, you will be asked for + your specific card in the following questions. + +if WLAN_VENDOR_PURELIFI + +config PURELIFI + + tristate "pureLiFi device support" + depends on CFG80211 && MAC80211 && USB + help + This driver makes the adapter appear as a normal WLAN interface. + + The pureLiFi device requires external STA firmware to be loaded. + + To compile this driver as a module, choose M here: the module will + be called purelifi. + +endif # WLAN_VENDOR_PURELIFI diff --git a/drivers/net/wireless/purelifi/Makefile b/drivers/net/wireless/purelifi/Makefile new file mode 100644 index ..1f20055e741f --- /dev/null +++ b/drivers/net/wireless/purelifi/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_PURELIFI) := purelifi.o +purelifi-objs += chip.o usb.o mac.o diff --git a/drivers/net/wireless/purelifi/chip.c b/drivers/net/wireless/purelifi/chip.c new file mode 100644 index ..ea1e58426c92 --- /dev/null +++ b/drivers/net/wireless/purelifi/chip.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include + +#include "chip.h" +#include "mac.h" +#include "usb.h" + +void purelifi_chip_init(struct purelifi_chip *chip, + struct ieee80211_hw *hw, +
[PATCH v2 11/17] ASoC: sun8i-codec: Constrain to compatible sample rates
While another stream is active, only allow userspace to use sample rates that are compatible with the current SYSCLK frequency. This ensures the actual sample rate will always match what is given in hw_params. Acked-by: Maxime Ripard Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun8i-codec.c | 57 --- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 468fa5f71bd3..0e8b0ac31fed 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -121,16 +121,18 @@ struct sun8i_codec_quirks { bool lrck_inversion : 1; }; struct sun8i_codec { struct regmap *regmap; struct clk *clk_module; const struct sun8i_codec_quirks *quirks; struct sun8i_codec_aif aifs[SUN8I_CODEC_NAIFS]; + unsigned intsysclk_rate; + int sysclk_refcnt; }; static int sun8i_codec_runtime_resume(struct device *dev) { struct sun8i_codec *scodec = dev_get_drvdata(dev); int ret; regcache_cache_only(scodec->regmap, false); @@ -319,16 +321,57 @@ static int sun8i_codec_set_tdm_slot(struct snd_soc_dai *dai, return -EINVAL; aif->slots = slots; aif->slot_width = slot_width; return 0; } +static const unsigned int sun8i_codec_rates[] = { + 7350, 8000, 11025, 12000, 14700, 16000, 22050, 24000, +29400, 32000, 44100, 48000, 88200, 96000, 176400, 192000, +}; + +static const struct snd_pcm_hw_constraint_list sun8i_codec_all_rates = { + .list = sun8i_codec_rates, + .count = ARRAY_SIZE(sun8i_codec_rates), +}; + +static const struct snd_pcm_hw_constraint_list sun8i_codec_22M_rates = { + .list = sun8i_codec_rates, + .count = ARRAY_SIZE(sun8i_codec_rates), + .mask = 0x, +}; + +static const struct snd_pcm_hw_constraint_list sun8i_codec_24M_rates = { + .list = sun8i_codec_rates, + .count = ARRAY_SIZE(sun8i_codec_rates), + .mask = 0x, +}; + +static int sun8i_codec_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); + const struct snd_pcm_hw_constraint_list *list; + + if (!scodec->sysclk_refcnt) + list = &sun8i_codec_all_rates; + else if (scodec->sysclk_rate == 22579200) + list = &sun8i_codec_22M_rates; + else if (scodec->sysclk_rate == 24576000) + list = &sun8i_codec_24M_rates; + else + return -EINVAL; + + return snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, list); +} + struct sun8i_codec_clk_div { u8 div; u8 val; }; static const struct sun8i_codec_clk_div sun8i_codec_bclk_div[] = { { .div = 1, .val = 0 }, { .div = 2, .val = 1 }, @@ -341,22 +384,21 @@ static const struct sun8i_codec_clk_div sun8i_codec_bclk_div[] = { { .div = 32,.val = 8 }, { .div = 48,.val = 9 }, { .div = 64,.val = 10 }, { .div = 96,.val = 11 }, { .div = 128, .val = 12 }, { .div = 192, .val = 13 }, }; -static u8 sun8i_codec_get_bclk_div(struct sun8i_codec *scodec, +static u8 sun8i_codec_get_bclk_div(unsigned int sysclk_rate, unsigned int lrck_div_order, unsigned int sample_rate) { - unsigned long clk_rate = clk_get_rate(scodec->clk_module); - unsigned int div = clk_rate / sample_rate >> lrck_div_order; + unsigned int div = sysclk_rate / sample_rate >> lrck_div_order; unsigned int best_val = 0, best_diff = ~0; int i; for (i = 0; i < ARRAY_SIZE(sun8i_codec_bclk_div); i++) { const struct sun8i_codec_clk_div *bdiv = &sun8i_codec_bclk_div[i]; unsigned int diff = abs(bdiv->div - div); if (diff < best_diff) { @@ -383,16 +425,17 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); struct sun8i_codec_aif *aif = &scodec->aifs[dai->id]; unsigned int sample_rate = params_rate(params); unsigned int slots = aif->slots ?: params_channels(params); unsigned int slot_width = aif->slot_width ?: params_width(params); + unsigned int sysclk_rate = clk_get_rate(scodec->clk_module); int lrck_div_order, word_size; u8 bclk_div; /* word size */ switch (params_width(params)) { case 8: word_size =
[PATCH v2 02/17] ASoC: sun8i-codec: Program DAI format before clock inversion
The LRCK inversion bit has a different meaning in DSP mode: it selects between the DSP A and DSP B formats. To support this, we need to know if the selected format is a DSP format. One easy way to do this is to set the format field before the clock inversion fields. Acked-by: Maxime Ripard Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun8i-codec.c | 46 +-- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 6413873a0584..53c9289a4249 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -168,33 +168,55 @@ static int sun8i_codec_get_hw_rate(struct snd_pcm_hw_params *params) default: return -EINVAL; } } static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); - u32 value; + u32 format, value; /* clock masters */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: /* Codec slave, DAI master */ value = 0x1; break; case SND_SOC_DAIFMT_CBM_CFM: /* Codec Master, DAI slave */ value = 0x0; break; default: return -EINVAL; } regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, BIT(SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD), value << SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD); + /* DAI format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + format = 0x0; + break; + case SND_SOC_DAIFMT_LEFT_J: + format = 0x1; + break; + case SND_SOC_DAIFMT_RIGHT_J: + format = 0x2; + break; + case SND_SOC_DAIFMT_DSP_A: + case SND_SOC_DAIFMT_DSP_B: + format = 0x3; + break; + default: + return -EINVAL; + } + regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, + SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK, + format << SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT); + /* clock inversion */ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: /* Normal */ value = 0x0; break; case SND_SOC_DAIFMT_IB_IF: /* Inversion */ value = 0x1; break; @@ -215,38 +237,16 @@ static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) * that the codec probably gets it backward, and we have to * invert the value here. */ value ^= scodec->quirks->lrck_inversion; regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, BIT(SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV), value << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV); - /* DAI format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - value = 0x0; - break; - case SND_SOC_DAIFMT_LEFT_J: - value = 0x1; - break; - case SND_SOC_DAIFMT_RIGHT_J: - value = 0x2; - break; - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - value = 0x3; - break; - default: - return -EINVAL; - } - regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, - SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK, - value << SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT); - return 0; } struct sun8i_codec_clk_div { u8 div; u8 val; }; -- 2.26.2
[PATCH v2 09/17] ASoC: sun8i-codec: Enable all supported sample rates
The system sample rate programmed into the hardware is really a clock divider from SYSCLK to the ADC and DAC. Since we support two SYSCLK frequencies, we can use all sample rates corresponding to one of those frequencies divided by any available divisor. This commit enables support for those sample rates. It also stops advertising support for a 64 kHz sample rate, which is not supported. Acked-by: Maxime Ripard Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun8i-codec.c | 17 ++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 21104e6e8892..38349d85fb17 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -89,16 +89,23 @@ #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12) #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8) #define SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV_MASK GENMASK(14, 13) #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK GENMASK(12, 9) #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK GENMASK(8, 6) #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK GENMASK(5, 4) #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK GENMASK(3, 2) +#define SUN8I_CODEC_PCM_RATES (SNDRV_PCM_RATE_8000_48000|\ +SNDRV_PCM_RATE_88200 |\ +SNDRV_PCM_RATE_96000 |\ +SNDRV_PCM_RATE_176400|\ +SNDRV_PCM_RATE_192000|\ +SNDRV_PCM_RATE_KNOT) + enum { SUN8I_CODEC_AIF1, SUN8I_CODEC_NAIFS }; struct sun8i_codec_aif { unsigned intslots; unsigned intslot_width; @@ -142,37 +149,41 @@ static int sun8i_codec_runtime_suspend(struct device *dev) return 0; } static int sun8i_codec_get_hw_rate(struct snd_pcm_hw_params *params) { unsigned int rate = params_rate(params); switch (rate) { - case 8000: case 7350: + case 8000: return 0x0; case 11025: return 0x1; case 12000: return 0x2; + case 14700: case 16000: return 0x3; case 22050: return 0x4; case 24000: return 0x5; + case 29400: case 32000: return 0x6; case 44100: return 0x7; case 48000: return 0x8; + case 88200: case 96000: return 0x9; + case 176400: case 192000: return 0xa; default: return -EINVAL; } } static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) @@ -408,26 +419,26 @@ static struct snd_soc_dai_driver sun8i_codec_dais[] = { .name = "sun8i-codec-aif1", .id = SUN8I_CODEC_AIF1, .ops= &sun8i_codec_dai_ops, /* capture capabilities */ .capture = { .stream_name= "AIF1 Capture", .channels_min = 1, .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = SUN8I_CODEC_PCM_RATES, .formats= SNDRV_PCM_FMTBIT_S16_LE, .sig_bits = 24, }, /* playback capabilities */ .playback = { .stream_name= "AIF1 Playback", .channels_min = 1, .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = SUN8I_CODEC_PCM_RATES, .formats= SNDRV_PCM_FMTBIT_S16_LE, }, .symmetric_rates= true, .symmetric_channels = true, .symmetric_samplebits = true, }, }; -- 2.26.2
[PATCH v2 15/17] ASoC: sun8i-codec: Generalize AIF clock control
The AIF clock control register has the same layout for all three AIFs. The only difference between them is that AIF3 is missing some fields. We can reuse the same register field definitions for all three registers, and use the DAI ID to select the correct register address. Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun8i-codec.c | 62 ++- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index e3abf8363d9b..6aa8751f7fa0 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -37,23 +37,23 @@ #define SUN8I_MOD_CLK_ENA_DAC 2 #define SUN8I_MOD_RST_CTL 0x014 #define SUN8I_MOD_RST_CTL_AIF1 15 #define SUN8I_MOD_RST_CTL_ADC 3 #define SUN8I_MOD_RST_CTL_DAC 2 #define SUN8I_SYS_SR_CTRL 0x018 #define SUN8I_SYS_SR_CTRL_AIF1_FS 12 #define SUN8I_SYS_SR_CTRL_AIF2_FS 8 -#define SUN8I_AIF1CLK_CTRL 0x040 -#define SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD 15 -#define SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV13 -#define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV 9 -#define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV 6 -#define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ 4 -#define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT 2 +#define SUN8I_AIF_CLK_CTRL(n) (0x040 * (1 + (n))) +#define SUN8I_AIF_CLK_CTRL_MSTR_MOD15 +#define SUN8I_AIF_CLK_CTRL_CLK_INV 13 +#define SUN8I_AIF_CLK_CTRL_BCLK_DIV9 +#define SUN8I_AIF_CLK_CTRL_LRCK_DIV6 +#define SUN8I_AIF_CLK_CTRL_WORD_SIZ4 +#define SUN8I_AIF_CLK_CTRL_DATA_FMT2 #define SUN8I_AIF1_ADCDAT_CTRL 0x044 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA 15 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA 14 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC 10 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC 8 #define SUN8I_AIF1_DACDAT_CTRL 0x048 #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA 15 #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA 14 @@ -83,21 +83,21 @@ #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R10 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR9 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR8 #define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK GENMASK(9, 8) #define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK GENMASK(5, 4) #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12) #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8) -#define SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV_MASK GENMASK(14, 13) -#define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK GENMASK(12, 9) -#define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK GENMASK(8, 6) -#define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK GENMASK(5, 4) -#define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK GENMASK(3, 2) +#define SUN8I_AIF_CLK_CTRL_CLK_INV_MASKGENMASK(14, 13) +#define SUN8I_AIF_CLK_CTRL_BCLK_DIV_MASK GENMASK(12, 9) +#define SUN8I_AIF_CLK_CTRL_LRCK_DIV_MASK GENMASK(8, 6) +#define SUN8I_AIF_CLK_CTRL_WORD_SIZ_MASK GENMASK(5, 4) +#define SUN8I_AIF_CLK_CTRL_DATA_FMT_MASK GENMASK(3, 2) #define SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE 48000 #define SUN8I_CODEC_PCM_FORMATS(SNDRV_PCM_FMTBIT_S8 |\ SNDRV_PCM_FMTBIT_S16_LE |\ SNDRV_PCM_FMTBIT_S20_LE |\ SNDRV_PCM_FMTBIT_S24_LE |\ SNDRV_PCM_FMTBIT_S20_3LE|\ @@ -236,19 +236,20 @@ static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) value = 0x1; break; case SND_SOC_DAIFMT_CBM_CFM: /* Codec Master, DAI slave */ value = 0x0; break; default: return -EINVAL; } - regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, - BIT(SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD), - value << SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD); + + regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id), + BIT(SUN8I_AIF_CLK_CTRL_MSTR_MOD), + value << SUN8I_AIF_CLK_CTRL_MSTR_MOD); /* DAI format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: format = 0x0; break; case SND_SOC_DAIFMT_LEFT_J: format = 0x1; @@ -262,19 +263,20 @@ static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) break; case SND_SOC_
[PATCH v2 17/17] ASoC: sun8i-codec: Add the AIF3 DAI, widgets, and routes
AIF3 has some differences from AIF1 and AIF2: - It supports one channel only - It supports master mode only - It is not directly connected to any of the mixers; instead all audio goes through a mux with AIF2. - It does not have its own clock dividers; instead it reuses AIF2 BCLK and LRCK. This means that when both AIF2 and AIF3 are active, they must use the same sample rate and total frame width. Since AIF2 and AIF3 are only used for codec2codec DAI links, constraints are not applicable here; the only thing we can do when the rates don't match is report an error. Make the necessary adjustments to support this AIF. Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun8i-codec.c | 138 -- 1 file changed, 130 insertions(+), 8 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 6a8232e07983..180442c62be1 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -29,21 +29,23 @@ #define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL (0x2 << 4) #define SUN8I_SYSCLK_CTL_SYSCLK_ENA3 #define SUN8I_SYSCLK_CTL_SYSCLK_SRC0 #define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK(0x0 << 0) #define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF2CLK(0x1 << 0) #define SUN8I_MOD_CLK_ENA 0x010 #define SUN8I_MOD_CLK_ENA_AIF1 15 #define SUN8I_MOD_CLK_ENA_AIF2 14 +#define SUN8I_MOD_CLK_ENA_AIF3 13 #define SUN8I_MOD_CLK_ENA_ADC 3 #define SUN8I_MOD_CLK_ENA_DAC 2 #define SUN8I_MOD_RST_CTL 0x014 #define SUN8I_MOD_RST_CTL_AIF1 15 #define SUN8I_MOD_RST_CTL_AIF2 14 +#define SUN8I_MOD_RST_CTL_AIF3 13 #define SUN8I_MOD_RST_CTL_ADC 3 #define SUN8I_MOD_RST_CTL_DAC 2 #define SUN8I_SYS_SR_CTRL 0x018 #define SUN8I_SYS_SR_CTRL_AIF1_FS 12 #define SUN8I_SYS_SR_CTRL_AIF2_FS 8 #define SUN8I_AIF_CLK_CTRL(n) (0x040 * (1 + (n))) #define SUN8I_AIF_CLK_CTRL_MSTR_MOD15 #define SUN8I_AIF_CLK_CTRL_CLK_INV 13 @@ -84,16 +86,19 @@ #define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA0L 15 #define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA1L 14 #define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF2DACR 13 #define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_ADCL 12 #define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA0R 11 #define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA1R 10 #define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF2DACL 9 #define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_ADCR 8 +#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF1 (0x0 << 0) +#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF2 (0x1 << 0) +#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF1CLK (0x2 << 0) #define SUN8I_AIF3_PATH_CTRL 0x0cc #define SUN8I_AIF3_PATH_CTRL_AIF3_ADC_SRC 10 #define SUN8I_AIF3_PATH_CTRL_AIF2_DAC_SRC 8 #define SUN8I_AIF3_PATH_CTRL_AIF3_PINS_TRI 7 #define SUN8I_ADC_DIG_CTRL 0x100 #define SUN8I_ADC_DIG_CTRL_ENAD15 #define SUN8I_ADC_DIG_CTRL_ADOUT_DTS 2 #define SUN8I_ADC_DIG_CTRL_ADOUT_DLY 1 @@ -113,16 +118,17 @@ #define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK GENMASK(5, 4) #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12) #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8) #define SUN8I_AIF_CLK_CTRL_CLK_INV_MASKGENMASK(14, 13) #define SUN8I_AIF_CLK_CTRL_BCLK_DIV_MASK GENMASK(12, 9) #define SUN8I_AIF_CLK_CTRL_LRCK_DIV_MASK GENMASK(8, 6) #define SUN8I_AIF_CLK_CTRL_WORD_SIZ_MASK GENMASK(5, 4) #define SUN8I_AIF_CLK_CTRL_DATA_FMT_MASK GENMASK(3, 2) +#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_MASK GENMASK(1, 0) #define SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE 48000 #define SUN8I_CODEC_PCM_FORMATS(SNDRV_PCM_FMTBIT_S8 |\ SNDRV_PCM_FMTBIT_S16_LE |\ SNDRV_PCM_FMTBIT_S20_LE |\ SNDRV_PCM_FMTBIT_S24_LE |\ SNDRV_PCM_FMTBIT_S20_3LE|\ @@ -133,20 +139,22 @@ SNDRV_PCM_RATE_96000 |\ SNDRV_PCM_RATE_176400|\ SNDRV_PCM_RATE_192000|\ SNDRV_PCM_RATE_KNOT) enum { SUN8I_CODEC_AIF1, SUN8I_CODEC_AIF2, + SUN8I_CODEC_AIF3, SUN8I_CODEC_NAIFS }; struct sun8i_codec_aif { + unsigned intlrck_div_order; unsi
[PATCH v2 16/17] ASoC: sun8i-codec: Add the AIF2 DAI, widgets, and routes
This adds support for AIF2, which is stereo and has fullly independent clocking capability, making it very similar to AIF1. Acked-by: Maxime Ripard Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun8i-codec.c | 215 ++ 1 file changed, 215 insertions(+) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 6aa8751f7fa0..6a8232e07983 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -28,20 +28,22 @@ #define SUN8I_SYSCLK_CTL_AIF2CLK_ENA 7 #define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL (0x2 << 4) #define SUN8I_SYSCLK_CTL_SYSCLK_ENA3 #define SUN8I_SYSCLK_CTL_SYSCLK_SRC0 #define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK(0x0 << 0) #define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF2CLK(0x1 << 0) #define SUN8I_MOD_CLK_ENA 0x010 #define SUN8I_MOD_CLK_ENA_AIF1 15 +#define SUN8I_MOD_CLK_ENA_AIF2 14 #define SUN8I_MOD_CLK_ENA_ADC 3 #define SUN8I_MOD_CLK_ENA_DAC 2 #define SUN8I_MOD_RST_CTL 0x014 #define SUN8I_MOD_RST_CTL_AIF1 15 +#define SUN8I_MOD_RST_CTL_AIF2 14 #define SUN8I_MOD_RST_CTL_ADC 3 #define SUN8I_MOD_RST_CTL_DAC 2 #define SUN8I_SYS_SR_CTRL 0x018 #define SUN8I_SYS_SR_CTRL_AIF1_FS 12 #define SUN8I_SYS_SR_CTRL_AIF2_FS 8 #define SUN8I_AIF_CLK_CTRL(n) (0x040 * (1 + (n))) #define SUN8I_AIF_CLK_CTRL_MSTR_MOD15 #define SUN8I_AIF_CLK_CTRL_CLK_INV 13 @@ -63,16 +65,39 @@ #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L 15 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL 14 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL 13 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR 12 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R 11 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR 10 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR 9 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL 8 +#define SUN8I_AIF2_ADCDAT_CTRL 0x084 +#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_ENA 15 +#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_ENA 14 +#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_SRC 10 +#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_SRC 8 +#define SUN8I_AIF2_DACDAT_CTRL 0x088 +#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_ENA 15 +#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_ENA 14 +#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_SRC 10 +#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_SRC 8 +#define SUN8I_AIF2_MXR_SRC 0x08c +#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA0L 15 +#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA1L 14 +#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF2DACR 13 +#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_ADCL 12 +#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA0R 11 +#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA1R 10 +#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF2DACL 9 +#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_ADCR 8 +#define SUN8I_AIF3_PATH_CTRL 0x0cc +#define SUN8I_AIF3_PATH_CTRL_AIF3_ADC_SRC 10 +#define SUN8I_AIF3_PATH_CTRL_AIF2_DAC_SRC 8 +#define SUN8I_AIF3_PATH_CTRL_AIF3_PINS_TRI 7 #define SUN8I_ADC_DIG_CTRL 0x100 #define SUN8I_ADC_DIG_CTRL_ENAD15 #define SUN8I_ADC_DIG_CTRL_ADOUT_DTS 2 #define SUN8I_ADC_DIG_CTRL_ADOUT_DLY 1 #define SUN8I_DAC_DIG_CTRL 0x120 #define SUN8I_DAC_DIG_CTRL_ENDA15 #define SUN8I_DAC_MXR_SRC 0x130 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L15 @@ -107,16 +132,17 @@ SNDRV_PCM_RATE_88200 |\ SNDRV_PCM_RATE_96000 |\ SNDRV_PCM_RATE_176400|\ SNDRV_PCM_RATE_192000|\ SNDRV_PCM_RATE_KNOT) enum { SUN8I_CODEC_AIF1, + SUN8I_CODEC_AIF2, SUN8I_CODEC_NAIFS }; struct sun8i_codec_aif { unsigned intsample_rate; unsigned intslots; unsigned intslot_width; unsigned intactive_streams : 2; @@ -358,16 +384,20 @@ static const struct snd_pcm_hw_constraint_list sun8i_codec_24M_rates = { }; static int sun8i_codec_startup(struct snd_pcm_substream *substream, struct snd_s
[PATCH v2 05/17] ASoC: sun8i-codec: Round up the LRCK divisor
The codec supports only power-of-two BCLK/LRCK divisors. If either the slot width or the number of slots is not a power of two, the LRCK divisor must be rounded up to provide enough space. To do that, use order_base_2 (instead of ilog2, which rounds down). Since the rounded divisor is also needed for setting the SYSCLK/BCLK divisor, return the order base 2 instead of fully calculating the hardware register encoding. Acked-by: Maxime Ripard Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun8i-codec.c | 22 -- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 82576066c249..92fcef45097d 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -300,33 +300,35 @@ static u8 sun8i_codec_get_bclk_div(struct sun8i_codec *scodec, best_diff = diff; best_val = bdiv->val; } } return best_val; } -static int sun8i_codec_get_lrck_div(unsigned int channels, - unsigned int word_size) +static int sun8i_codec_get_lrck_div_order(unsigned int slots, + unsigned int slot_width) { - unsigned int div = word_size * channels; + unsigned int div = slots * slot_width; if (div < 16 || div > 256) return -EINVAL; - return ilog2(div) - 4; + return order_base_2(div); } static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); - int lrck_div, sample_rate, word_size; + unsigned int slots = params_channels(params); + unsigned int slot_width = params_width(params); + int lrck_div_order, sample_rate, word_size; u8 bclk_div; /* word size */ switch (params_width(params)) { case 8: word_size = 0x0; break; case 16: @@ -346,24 +348,24 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK, word_size << SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ); bclk_div = sun8i_codec_get_bclk_div(scodec, params_rate(params), 16); regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK, bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV); - lrck_div = sun8i_codec_get_lrck_div(params_channels(params), - params_physical_width(params)); - if (lrck_div < 0) - return lrck_div; + /* LRCK divider (BCLK/LRCK ratio) */ + lrck_div_order = sun8i_codec_get_lrck_div_order(slots, slot_width); + if (lrck_div_order < 0) + return lrck_div_order; regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK, - lrck_div << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV); + (lrck_div_order - 4) << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV); sample_rate = sun8i_codec_get_hw_rate(params); if (sample_rate < 0) return sample_rate; regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL, SUN8I_SYS_SR_CTRL_AIF1_FS_MASK, sample_rate << SUN8I_SYS_SR_CTRL_AIF1_FS); -- 2.26.2
[PATCH v2 03/17] ASoC: sun8i-codec: Enable all supported clock inversions
When using the I2S, LEFT_J, or RIGHT_J format, the hardware supports independent BCLK and LRCK inversion control. When using DSP_A or DSP_B, LRCK inversion is not supported. The register bit is repurposed to select between DSP_A and DSP_B. Extend the driver to support this. Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun8i-codec.c | 61 ++- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 53c9289a4249..77eb0fd01e3d 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -39,18 +39,17 @@ #define SUN8I_MOD_RST_CTL_AIF1 15 #define SUN8I_MOD_RST_CTL_ADC 3 #define SUN8I_MOD_RST_CTL_DAC 2 #define SUN8I_SYS_SR_CTRL 0x018 #define SUN8I_SYS_SR_CTRL_AIF1_FS 12 #define SUN8I_SYS_SR_CTRL_AIF2_FS 8 #define SUN8I_AIF1CLK_CTRL 0x040 #define SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD 15 -#define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV 14 -#define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV 13 +#define SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV13 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV 9 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV 6 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ 4 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16(1 << 4) #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT 2 #define SUN8I_AIF1_ADCDAT_CTRL 0x044 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA 15 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA 14 @@ -85,16 +84,17 @@ #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R10 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR9 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR8 #define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK GENMASK(9, 8) #define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK GENMASK(5, 4) #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12) #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8) +#define SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV_MASK GENMASK(14, 13) #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK GENMASK(12, 9) #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK GENMASK(8, 6) #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK GENMASK(5, 4) #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK GENMASK(3, 2) enum { SUN8I_CODEC_AIF1, SUN8I_CODEC_NAIFS @@ -168,17 +168,17 @@ static int sun8i_codec_get_hw_rate(struct snd_pcm_hw_params *params) default: return -EINVAL; } } static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); - u32 format, value; + u32 dsp_format, format, invert, value; /* clock masters */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: /* Codec slave, DAI master */ value = 0x1; break; case SND_SOC_DAIFMT_CBM_CFM: /* Codec Master, DAI slave */ value = 0x0; @@ -197,55 +197,72 @@ static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) break; case SND_SOC_DAIFMT_LEFT_J: format = 0x1; break; case SND_SOC_DAIFMT_RIGHT_J: format = 0x2; break; case SND_SOC_DAIFMT_DSP_A: + format = 0x3; + dsp_format = 0x0; /* Set LRCK_INV to 0 */ + break; case SND_SOC_DAIFMT_DSP_B: format = 0x3; + dsp_format = 0x1; /* Set LRCK_INV to 1 */ break; default: return -EINVAL; } regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK, format << SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT); /* clock inversion */ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: /* Normal */ - value = 0x0; + invert = 0x0; break; - case SND_SOC_DAIFMT_IB_IF: /* Inversion */ - value = 0x1; + case SND_SOC_DAIFMT_NB_IF: /* Inverted LRCK */ + invert = 0x1; + break; + case SND_SOC_DAIFMT_IB_NF: /* Inverted BCLK */ + invert = 0x2; + break; + case SND_SOC_DAIFMT_IB_IF: /* Both inverted */ + invert = 0x3; break; default: return -EINVAL; } - regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, - BIT(SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV), - value << SUN8I_AIF1CLK_CTRL_
[PATCH v2 08/17] ASoC: sun8i-codec: Enforce symmetric DAI parameters
The AIFs have a single register controlling DAI parameters in both directions, including BCLK/LRCK divisor and word size. The DAIs produce only noise or silence if any of these parameters is wrong. Therefore, we need to enforce symmetry for these parameters, so starting a new substream will not break an existing substream. Acked-by: Maxime Ripard Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun8i-codec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 49e763d1891b..21104e6e8892 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -420,16 +420,19 @@ static struct snd_soc_dai_driver sun8i_codec_dais[] = { /* playback capabilities */ .playback = { .stream_name= "AIF1 Playback", .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_192000, .formats= SNDRV_PCM_FMTBIT_S16_LE, }, + .symmetric_rates= true, + .symmetric_channels = true, + .symmetric_samplebits = true, }, }; static const char *const sun8i_aif_stereo_mux_enum_values[] = { "Stereo", "Reverse Stereo", "Sum Mono", "Mix Mono" }; static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_ad0_stereo_mux_enum, -- 2.26.2
[PATCH v2 04/17] ASoC: sun8i-codec: Use the provided word size
The hardware supports 8 to 24-bit word sizes on all three of its DAIs, only one of which is connected to the CPU DAI. Program the word size based on the actual selected format, instead of assuming limitations from another driver (which, incedentally, has patches pending to remove that limitation). Acked-by: Maxime Ripard Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun8i-codec.c | 27 --- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 77eb0fd01e3d..82576066c249 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -43,17 +43,16 @@ #define SUN8I_SYS_SR_CTRL_AIF1_FS 12 #define SUN8I_SYS_SR_CTRL_AIF2_FS 8 #define SUN8I_AIF1CLK_CTRL 0x040 #define SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD 15 #define SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV13 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV 9 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV 6 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ 4 -#define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16(1 << 4) #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT 2 #define SUN8I_AIF1_ADCDAT_CTRL 0x044 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA 15 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA 14 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC 10 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC 8 #define SUN8I_AIF1_DACDAT_CTRL 0x048 #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA 15 @@ -317,26 +316,40 @@ static int sun8i_codec_get_lrck_div(unsigned int channels, return ilog2(div) - 4; } static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); - int sample_rate, lrck_div; + int lrck_div, sample_rate, word_size; u8 bclk_div; - /* -* The CPU DAI handles only a sample of 16 bits. Configure the -* codec to handle this type of sample resolution. -*/ + /* word size */ + switch (params_width(params)) { + case 8: + word_size = 0x0; + break; + case 16: + word_size = 0x1; + break; + case 20: + word_size = 0x2; + break; + case 24: + word_size = 0x3; + break; + default: + return -EINVAL; + } + regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK, - SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16); + word_size << SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ); bclk_div = sun8i_codec_get_bclk_div(scodec, params_rate(params), 16); regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK, bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV); lrck_div = sun8i_codec_get_lrck_div(params_channels(params), params_physical_width(params)); -- 2.26.2
[PATCH v2 01/17] ASoC: sun8i-codec: Prepare to extend the DAI driver
In preparation for adding additional DAIs to this component, convert the DAI driver definition to an array. Since this changes all of the lines in the definition anyway, let's move it closer to the ops function definitions, instead of on the far side of the DAPM arrays. And while moving the DAI driver ops, rename the set_fmt hook to match the usual naming scheme. Give the existing DAI an explicit ID and more meaningful stream names, so it will remain unique as more DAIs are added. The AIF widget streams must be updated to match. Acked-by: Maxime Ripard Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun8i-codec.c | 76 +++ 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 7590c4b04d14..6413873a0584 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -90,16 +90,21 @@ #define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK GENMASK(5, 4) #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12) #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8) #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK GENMASK(12, 9) #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK GENMASK(8, 6) #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK GENMASK(5, 4) #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK GENMASK(3, 2) +enum { + SUN8I_CODEC_AIF1, + SUN8I_CODEC_NAIFS +}; + struct sun8i_codec_quirks { bool legacy_widgets : 1; bool lrck_inversion : 1; }; struct sun8i_codec { struct regmap *regmap; struct clk *clk_module; @@ -160,17 +165,17 @@ static int sun8i_codec_get_hw_rate(struct snd_pcm_hw_params *params) return 0x9; case 192000: return 0xa; default: return -EINVAL; } } -static int sun8i_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); u32 value; /* clock masters */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: /* Codec slave, DAI master */ value = 0x1; @@ -331,16 +336,46 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL, SUN8I_SYS_SR_CTRL_AIF1_FS_MASK, sample_rate << SUN8I_SYS_SR_CTRL_AIF1_FS); return 0; } +static const struct snd_soc_dai_ops sun8i_codec_dai_ops = { + .set_fmt= sun8i_codec_set_fmt, + .hw_params = sun8i_codec_hw_params, +}; + +static struct snd_soc_dai_driver sun8i_codec_dais[] = { + { + .name = "sun8i-codec-aif1", + .id = SUN8I_CODEC_AIF1, + .ops= &sun8i_codec_dai_ops, + /* capture capabilities */ + .capture = { + .stream_name= "AIF1 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats= SNDRV_PCM_FMTBIT_S16_LE, + .sig_bits = 24, + }, + /* playback capabilities */ + .playback = { + .stream_name= "AIF1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats= SNDRV_PCM_FMTBIT_S16_LE, + }, + }, +}; + static const char *const sun8i_aif_stereo_mux_enum_values[] = { "Stereo", "Reverse Stereo", "Sum Mono", "Mix Mono" }; static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_ad0_stereo_mux_enum, SUN8I_AIF1_ADCDAT_CTRL, SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC, SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC, @@ -433,20 +468,20 @@ static const struct snd_soc_dapm_widget sun8i_codec_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("ADC", SUN8I_ADC_DIG_CTRL, SUN8I_ADC_DIG_CTRL_ENAD, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("DAC", SUN8I_DAC_DIG_CTRL, SUN8I_DAC_DIG_CTRL_ENDA, 0, NULL, 0), /* AIF "ADC" Outputs */ - SND_SOC_DAPM_AIF_OUT("AIF1 AD0L", "Capture", 0, + SND_SOC_DAPM_AIF_OUT("AIF1 AD0L", "AIF1 Capture", 0, SUN8I_AIF1_ADCDAT_CTRL, SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA, 0), - SND_SOC_DAPM_AIF_OUT("AIF1 AD0R", "Capture", 1, + SND_SOC_DAPM_AIF_OUT("AIF1 AD0R", "AIF1 Capture", 1, SUN
[PATCH v2 07/17] ASoC: sun8i-codec: Support the TDM slot binding
Now that BCLK and LRCK rate calculations in the driver can handle any hardware-supported slot width and number of slots, allow overriding those parameters from the device tree. Acked-by: Maxime Ripard Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun8i-codec.c | 28 ++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index ae885774c877..49e763d1891b 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -94,25 +94,31 @@ #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK GENMASK(5, 4) #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK GENMASK(3, 2) enum { SUN8I_CODEC_AIF1, SUN8I_CODEC_NAIFS }; +struct sun8i_codec_aif { + unsigned intslots; + unsigned intslot_width; +}; + struct sun8i_codec_quirks { bool legacy_widgets : 1; bool lrck_inversion : 1; }; struct sun8i_codec { struct regmap *regmap; struct clk *clk_module; const struct sun8i_codec_quirks *quirks; + struct sun8i_codec_aif aifs[SUN8I_CODEC_NAIFS]; }; static int sun8i_codec_runtime_resume(struct device *dev) { struct sun8i_codec *scodec = dev_get_drvdata(dev); int ret; regcache_cache_only(scodec->regmap, false); @@ -256,16 +262,32 @@ static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV_MASK, invert << SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV); return 0; } +static int sun8i_codec_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, unsigned int rx_mask, + int slots, int slot_width) +{ + struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); + struct sun8i_codec_aif *aif = &scodec->aifs[dai->id]; + + if (slot_width && !is_power_of_2(slot_width)) + return -EINVAL; + + aif->slots = slots; + aif->slot_width = slot_width; + + return 0; +} + struct sun8i_codec_clk_div { u8 div; u8 val; }; static const struct sun8i_codec_clk_div sun8i_codec_bclk_div[] = { { .div = 1, .val = 0 }, { .div = 2, .val = 1 }, @@ -316,18 +338,19 @@ static int sun8i_codec_get_lrck_div_order(unsigned int slots, return order_base_2(div); } static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); - unsigned int slots = params_channels(params); - unsigned int slot_width = params_width(params); + struct sun8i_codec_aif *aif = &scodec->aifs[dai->id]; + unsigned int slots = aif->slots ?: params_channels(params); + unsigned int slot_width = aif->slot_width ?: params_width(params); int lrck_div_order, sample_rate, word_size; u8 bclk_div; /* word size */ switch (params_width(params)) { case 8: word_size = 0x0; break; @@ -371,16 +394,17 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, SUN8I_SYS_SR_CTRL_AIF1_FS_MASK, sample_rate << SUN8I_SYS_SR_CTRL_AIF1_FS); return 0; } static const struct snd_soc_dai_ops sun8i_codec_dai_ops = { .set_fmt= sun8i_codec_set_fmt, + .set_tdm_slot = sun8i_codec_set_tdm_slot, .hw_params = sun8i_codec_hw_params, }; static struct snd_soc_dai_driver sun8i_codec_dais[] = { { .name = "sun8i-codec-aif1", .id = SUN8I_CODEC_AIF1, .ops= &sun8i_codec_dai_ops, -- 2.26.2
[PATCH v2 00/17] ASoC: sun8i-codec: support for AIF2 and AIF3
This series adds support the other two AIFs present in the sun8i codec, which can be used for codec2codec DAI links. This series first fills out the DAI driver, removing assumptions that were made for AIF1 (16 bits, 2 channels, certain clock inversions). Some new logic is required to handle 3 DAIs and the ADC/DAC sharing the same clock. Finally, it adds the new DAIs, and hooks them up with DAPM widgets and routes per the hardware topology. To minimize the number of patches in this series, related device tree patches (increasing #sound-dai-cells, adding new DAI links) will be sent separately. Changes from v1: - Patches 1-8 from v1 (DAPM changes) were merged - Prefixed AIF constants with "SUN8I_CODEC_" [1, 7, 10, 16, 17] - Renamed variables in sun8i_codec_set_fmt for clarity [3] - Update sysclk->sysclk_rate if later calls to hw_params change the sample rate (thanks Chen-Yu for reminding me of this) [11] - Select COMMON_CLK for clk_set_rate_exclusive [12] - Add comments and hopefully clarify the clock protection logic [12] - Make the error message more concise and put it on one line [12] - Drop the "reg" variable holding SUN8I_AIF_CLK_CTRL(dai->id) [15] - Rename "div_reg" to "clk_reg" and adjust comments for clarity [17] - Improve the AIF2/AIF3 rate mismatch error message [17] - Minor grammar/wording fixes in commit messages [2, 4, 7, 8, 16, 17] - Added Maxime's Acked-by: [1-2, 4-9, 11, 13-14, 16] Samuel Holland (17): ASoC: sun8i-codec: Prepare to extend the DAI driver ASoC: sun8i-codec: Program DAI format before clock inversion ASoC: sun8i-codec: Enable all supported clock inversions ASoC: sun8i-codec: Use the provided word size ASoC: sun8i-codec: Round up the LRCK divisor ASoC: sun8i-codec: Correct the BCLK divisor calculation ASoC: sun8i-codec: Support the TDM slot binding ASoC: sun8i-codec: Enforce symmetric DAI parameters ASoC: sun8i-codec: Enable all supported sample rates ASoC: sun8i-codec: Automatically set the system sample rate ASoC: sun8i-codec: Constrain to compatible sample rates ASoC: sun8i-codec: Protect the clock rate while streams are open ASoC: sun8i-codec: Require an exact BCLK divisor match ASoC: sun8i-codec: Enable all supported PCM formats ASoC: sun8i-codec: Generalize AIF clock control ASoC: sun8i-codec: Add the AIF2 DAI, widgets, and routes ASoC: sun8i-codec: Add the AIF3 DAI, widgets, and routes sound/soc/sunxi/Kconfig | 1 + sound/soc/sunxi/sun8i-codec.c | 834 -- 2 files changed, 699 insertions(+), 136 deletions(-) -- 2.26.2
[PATCH v2 06/17] ASoC: sun8i-codec: Correct the BCLK divisor calculation
Previously, the BCLK divisor calculation assumed zero padding and exactly two slots. In order to support the TDM slot binding and 20/24-bit word sizes, those assumptions must be removed. Due to hardware limitations, the BCLK/LRCK ratio is not as simple as "slot_width * slots". However, the correct value is already calculated elsewhere in this function, since it must also be programmed into the hardware. Reuse that value to calculate the correct SYSCLK/BCLK divisor. Acked-by: Maxime Ripard Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun8i-codec.c | 17 + 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 92fcef45097d..ae885774c877 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -279,21 +279,21 @@ static const struct sun8i_codec_clk_div sun8i_codec_bclk_div[] = { { .div = 48,.val = 9 }, { .div = 64,.val = 10 }, { .div = 96,.val = 11 }, { .div = 128, .val = 12 }, { .div = 192, .val = 13 }, }; static u8 sun8i_codec_get_bclk_div(struct sun8i_codec *scodec, - unsigned int rate, - unsigned int word_size) + unsigned int lrck_div_order, + unsigned int sample_rate) { unsigned long clk_rate = clk_get_rate(scodec->clk_module); - unsigned int div = clk_rate / rate / word_size / 2; + unsigned int div = clk_rate / sample_rate >> lrck_div_order; unsigned int best_val = 0, best_diff = ~0; int i; for (i = 0; i < ARRAY_SIZE(sun8i_codec_bclk_div); i++) { const struct sun8i_codec_clk_div *bdiv = &sun8i_codec_bclk_div[i]; unsigned int diff = abs(bdiv->div - div); if (diff < best_diff) { @@ -343,30 +343,31 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, default: return -EINVAL; } regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK, word_size << SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ); - bclk_div = sun8i_codec_get_bclk_div(scodec, params_rate(params), 16); - regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, - SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK, - bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV); - /* LRCK divider (BCLK/LRCK ratio) */ lrck_div_order = sun8i_codec_get_lrck_div_order(slots, slot_width); if (lrck_div_order < 0) return lrck_div_order; regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK, (lrck_div_order - 4) << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV); + /* BCLK divider (SYSCLK/BCLK ratio) */ + bclk_div = sun8i_codec_get_bclk_div(scodec, lrck_div_order, params_rate(params)); + regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, + SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK, + bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV); + sample_rate = sun8i_codec_get_hw_rate(params); if (sample_rate < 0) return sample_rate; regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL, SUN8I_SYS_SR_CTRL_AIF1_FS_MASK, sample_rate << SUN8I_SYS_SR_CTRL_AIF1_FS); -- 2.26.2
Re: [PATCH 2/2] clk: samsung: exynos-clkout: convert to module driver
On Tue, Oct 13, 2020 at 07:43:40PM -0700, Stephen Boyd wrote: > Quoting Krzysztof Kozlowski (2020-10-01 09:56:46) > > diff --git a/drivers/clk/samsung/clk-exynos-clkout.c > > b/drivers/clk/samsung/clk-exynos-clkout.c > > index 34ccb1d23bc3..68af082d4716 100644 > > --- a/drivers/clk/samsung/clk-exynos-clkout.c > > +++ b/drivers/clk/samsung/clk-exynos-clkout.c > > @@ -28,41 +31,103 @@ struct exynos_clkout { > [...] > > + if (!match) { > > + dev_err(dev, "cannot match parent device\n"); > > + return -EINVAL; > > + } > > + variant = match->data; > > + > > + *mux_mask = variant->mux_mask; > > + dev_err(dev, "MATCH: %x\n", variant->mux_mask); > > Is this a debug print? Debugging left over, thanks for catching this. I'll remove it. Best regards, Krzysztof
[PATCH 1/1] net: ftgmac100: Fix Aspeed ast2600 TX hang issue
The new HW arbitration feature on Aspeed ast2600 will cause MAC TX to hang when handling scatter-gather DMA. Disable the problematic feature by setting MAC register 0x58 bit28 and bit27. Signed-off-by: Dylan Hung --- drivers/net/ethernet/faraday/ftgmac100.c | 5 + drivers/net/ethernet/faraday/ftgmac100.h | 8 2 files changed, 13 insertions(+) diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index 87236206366f..00024dd41147 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -1817,6 +1817,11 @@ static int ftgmac100_probe(struct platform_device *pdev) priv->rxdes0_edorr_mask = BIT(30); priv->txdes0_edotr_mask = BIT(30); priv->is_aspeed = true; + /* Disable ast2600 problematic HW arbitration */ + if (of_device_is_compatible(np, "aspeed,ast2600-mac")) { + iowrite32(FTGMAC100_TM_DEFAULT, + priv->base + FTGMAC100_OFFSET_TM); + } } else { priv->rxdes0_edorr_mask = BIT(15); priv->txdes0_edotr_mask = BIT(15); diff --git a/drivers/net/ethernet/faraday/ftgmac100.h b/drivers/net/ethernet/faraday/ftgmac100.h index e5876a3fda91..63b3e02fab16 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.h +++ b/drivers/net/ethernet/faraday/ftgmac100.h @@ -169,6 +169,14 @@ #define FTGMAC100_MACCR_FAST_MODE (1 << 19) #define FTGMAC100_MACCR_SW_RST (1 << 31) +/* + * test mode control register + */ +#define FTGMAC100_TM_RQ_TX_VALID_DIS (1 << 28) +#define FTGMAC100_TM_RQ_RR_IDLE_PREV (1 << 27) +#define FTGMAC100_TM_DEFAULT \ + (FTGMAC100_TM_RQ_TX_VALID_DIS | FTGMAC100_TM_RQ_RR_IDLE_PREV) + /* * PHY control register */ -- 2.17.1
[PATCH 0/1] Fix Aspeed ast2600 MAC TX hang
This patch fixes the TX hang issue on Aspeed AST2600. Two HW arbitration features are added onto ast2600, but these features will cause MAC TX to hang when handling scatter-gather DMA. These two problematic features can be disabled by setting MAC register 0x58 bit28 and bit27. Dylan Hung (1): net: ftgmac100: Fix Aspeed ast2600 TX hang issue drivers/net/ethernet/faraday/ftgmac100.c | 5 + drivers/net/ethernet/faraday/ftgmac100.h | 8 2 files changed, 13 insertions(+) -- 2.17.1
[tip:x86/urgent] BUILD SUCCESS 081dd68c89061077930ec7776d98837cb64b0405
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/urgent branch HEAD: 081dd68c89061077930ec7776d98837cb64b0405 x86/platform/uv: Remove unused variable in UV5 NMI handler elapsed time: 724m configs tested: 83 configs skipped: 62 The following configs have been built successfully. More configs may be tested in the coming days. gcc tested configs: armvt8500_v6_v7_defconfig mips rt305x_defconfig arc haps_hs_smp_defconfig armkeystone_defconfig m68k sun3_defconfig powerpc stx_gp3_defconfig powerpc mpc834x_itx_defconfig arm rpc_defconfig m68k sun3x_defconfig ia64 alldefconfig arc axs103_defconfig arm davinci_all_defconfig arm pxa3xx_defconfig armdove_defconfig sh shx3_defconfig arm lpd270_defconfig ia64 allmodconfig ia64defconfig ia64 allyesconfig m68k allmodconfig m68kdefconfig m68k allyesconfig nios2 defconfig arc allyesconfig nds32 allnoconfig c6x allyesconfig nds32 defconfig nios2allyesconfig cskydefconfig alpha defconfig alphaallyesconfig xtensa allyesconfig h8300allyesconfig arc defconfig sh allmodconfig parisc defconfig s390 allyesconfig parisc allyesconfig s390defconfig i386 allyesconfig sparcallyesconfig sparc defconfig i386defconfig powerpc allyesconfig powerpc allmodconfig powerpc allnoconfig x86_64 randconfig-a004-20201013 x86_64 randconfig-a002-20201013 x86_64 randconfig-a006-20201013 x86_64 randconfig-a001-20201013 x86_64 randconfig-a003-20201013 x86_64 randconfig-a005-20201013 i386 randconfig-a005-20201013 i386 randconfig-a006-20201013 i386 randconfig-a001-20201013 i386 randconfig-a003-20201013 i386 randconfig-a004-20201013 i386 randconfig-a002-20201013 i386 randconfig-a016-20201013 i386 randconfig-a015-20201013 i386 randconfig-a013-20201013 i386 randconfig-a012-20201013 i386 randconfig-a011-20201013 i386 randconfig-a014-20201013 riscvnommu_k210_defconfig riscvallyesconfig riscvnommu_virt_defconfig riscv allnoconfig riscv defconfig riscv rv32_defconfig riscvallmodconfig x86_64 rhel x86_64 allyesconfig x86_64rhel-7.6-kselftests x86_64 defconfig x86_64 rhel-8.3 x86_64 kexec clang tested configs: x86_64 randconfig-a016-20201013 x86_64 randconfig-a015-20201013 x86_64 randconfig-a012-20201013 x86_64 randconfig-a013-20201013 x86_64 randconfig-a014-20201013 x86_64 randconfig-a011-20201013 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org
Re: [RFC PATCH 13/22] x86/fpu/xstate: Expand dynamic user state area on first use
On 10/13/20 6:11 PM, Andy Lutomirski wrote: > I have no problem with vmalloc(), but I do have a problem with > vfree() due to the IPIs that result. We need a cache or something. This sounds like the kind of thing we should just build into vmalloc() instead of having a bunch of callers implement their own caches. It shouldn't be too much of a challenge to have vmalloc() keep a cacheline or two of stats about common vmalloc() sizes and keep some pools around. It's not going to be hard to implement caches to reduce vfree()-induced churn, but I'm having a hard time imaging that it'll have anywhere near the benefits that it did for stacks. Tasks fundamentally come and go a *lot*, and those paths are hot. Tasks who go to the trouble to populate 8k or 64k of register state fundamentally *can't* come and go frequently. We also (probably) don't have to worry about AMX tasks doing fork()/exec() pairs and putting pressure on vmalloc(). Before an app can call out to library functions to do the fork, they've got to save the state off themselves and likely get it back to the init state. The fork() code can tell AMX is in the init state and decline to allocate actual space for the child. > I have to say: this mechanism is awful. Can we get away with skipping > the dynamic XSAVES mess entirely? What if we instead allocate > however much space we need as an array of pages and have one percpu > contiguous region. To save, we XSAVE(S or C) just the AMX state to > the percpu area and then copy it. To restore, we do the inverse. Or > would this kill the modified optimization and thus be horrible? Actually, I think the modified optimization would survive such a scheme: * copy page array into percpu area * XRSTORS from percpu area, modified optimization tuple is saved * run userspace * XSAVES back to percpu area. tuple matches, modified optimization is still in play * copy percpu area back to page array Since the XRSTORS->XSAVES pair is both done to the percpu area, the XSAVE tracking hardware never knows it isn't working on the "canonical" buffer (the page array). It seems a bit ugly, but it's not like an 8k memcpy() is *that* painful. The double dcache footprint isn't super nice, though. Chang, I think that leaves us with three possibilities: 1. use plain old vmalloc() 2. use vmalloc(), but implement caches for large XSAVE state, either in front of, or inside the vmalloc() API 3. Use a static per-cpu buffer for XSAVE*/XRSTOR* and memcpy() to/from a scattered list of pages. A #4 also comes to mind: Do something somewhat like kmap_atomic(). Map the scattered pages contiguously and use XSAVE*/XRSTOR* directly, but unmap immediately after XSAVE*/XRSTOR*. For ~12k of state, I suspect the ~400-500 cycles for 3 INVLPG's might beat out a memcpy() of 12k of state. Global TLB invalidations would not be required. I have to say, though, that I'd be OK with sticking with plain old vmalloc() for now.
Re: [RFC PATCH v2] checkpatch: add shebang check to EXECUTE_PERMISSIONS
On Wed, 2020-10-14 at 07:46 +0200, Lukas Bulwahn wrote: > Just one bigger project example: Comparing clang-format suggestions on > patches against checkpatch.pl suggestions are fine-tuning both of them to fit > to > the actual kernel style. Eek no. Mindless use of either tool isn't a great thing. Linux source code has generally be created with human readability in mind by humans, not scripts. Please don't try to replace human readable code with mindless tools. If there's something inappropriate in checkpatch, please mention it. There is a _lot_ of relatively inappropriate output in how clang-format changes existing code in the kernel. Try it and look at the results. Improving how .clang-format is created and its mechanisms (for example: continually out of date ForEachMacros lists) could be reasonably be done.
Re: [PATCH v4 2/2] PCI/ERR: Split the fatal and non-fatal error recovery handling
On 10/13/20 10:44 PM, Ethan Zhao wrote: This patch only reverts the commit bdb5ac85777d ? or you'd better separate the revert and code you added. We cannot revert the commit as it is. pcie_do_recovery() function and Documentation/* folder changed a lot since fatal and non-fatal error recovery paths were merged. So I modified the revert so that it can be applied to the latest kernel version. -- Sathyanarayanan Kuppuswamy Linux Kernel Developer
[PATCH] i2c: designware: fix slave omitted IC_INTR_STOP_DET
When an I2C slave works, sometimes both IC_INTR_RX_FULL and IC_INTR_STOP_DET are rising during an IRQ handle, especially when system is busy or too late to handle interrupts. If IC_INTR_RX_FULL is rising and the system doesn't handle immediately, IC_INTR_STOP_DET may be rising and the system has to handle these two events. For this there may be two problems: 1. IC_INTR_STOP_DET is rising after i2c_dw_read_clear_intrbits_slave() done: It seems invalidated because WRITE_REQUESTED is done after the 1st WRITE_RECEIVED. $ i2cset -f -y 2 0x42 0x00 0x41; dmesg -c [0][clear_intrbits]0x1 STATUS SLAVE_ACTIVITY=0x1 : RAW_INTR_STAT=0x514 : INTR_STAT=0x4 [1][irq_handler ]0x1 STATUS SLAVE_ACTIVITY=0x1 : RAW_INTR_STAT=0x514 : INTR_STAT=0x4 WRITE_RECEIVED [0][clear_intrbits]0x1 STATUS SLAVE_ACTIVITY=0x1 : RAW_INTR_STAT=0x514 : INTR_STAT=0x4 [1][irq_handler ]0x1 STATUS SLAVE_ACTIVITY=0x0 : RAW_INTR_STAT=0x714 : INTR_STAT=0x204 WRITE_REQUESTED WRITE_RECEIVED [0][clear_intrbits]0x1 STATUS SLAVE_ACTIVITY=0x0 : RAW_INTR_STAT=0x710 : INTR_STAT=0x200 [1][irq_handler ]0x1 STATUS SLAVE_ACTIVITY=0x0 : RAW_INTR_STAT=0x510 : INTR_STAT=0x0 STOP [2][clear_intrbits]0x1 STATUS SLAVE_ACTIVITY=0x0 : RAW_INTR_STAT=0x510 : INTR_STAT=0x0 t1: ISR with the 1st IC_INTR_RX_FULL. t2: Clear listed IC_INTR bits by i2c_dw_read_clear_intrbits_slave(). t3: Enter i2c_dw_irq_handler_slave() and then do i2c_slave_event(WRITE_RECEIVED) because if (stat & DW_IC_INTR_RX_FULL). t4: ISR with the 2nd IC_INTR_RX_FULL. t5: Clear listed IC_INTR bits by i2c_dw_read_clear_intrbits_slave(), while IC_INTR_STOP_DET has not risen yet. t6: Enter i2c_dw_irq_handler_slave() and then IC_INTR_STOP_DET is rising. i2c_slave_event(WRITE_REQUESTED) will be done first because if ((stat & DW_IC_INTR_RX_FULL) && (stat & DW_IC_INTR_STOP_DET)) and then doing i2c_slave_event(WRITE_RECEIVED). t7: do i2c_slave_event(STOP) due to IC_INTR_STOP_DET not be cleared yet. 2. Both IC_INTR_STOP_DET and IC_INTR_RX_FULL are rising before i2c_dw_read_clear_intrbits_slave(): STOP cannot wait because IC_INTR_STOP_DET is cleared by i2c_dw_read_clear_intrbits_slave(). $ i2cset -f -y 2 0x42 0x00 0x41; dmesg -c [0][clear_intrbits]0x1 STATUS SLAVE_ACTIVITY=0x1 : RAW_INTR_STAT=0x514 : INTR_STAT=0x4 [1][irq_handler ]0x1 STATUS SLAVE_ACTIVITY=0x1 : RAW_INTR_STAT=0x514 : INTR_STAT=0x4 WRITE_RECEIVED [0][clear_intrbits]0x1 STATUS SLAVE_ACTIVITY=0x0 : RAW_INTR_STAT=0x714 : INTR_STAT=0x204 [1][irq_handler ]0x1 STATUS SLAVE_ACTIVITY=0x0 : RAW_INTR_STAT=0x514 : INTR_STAT=0x4 WRITE_RECEIVED t1: ISR with the 1st IC_INTR_RX_FULL. t2: Clear listed IC_INTR bits by i2c_dw_read_clear_intrbits_slave(). t3: Enter i2c_dw_irq_handler_slave() and then do i2c_slave_event(WRITE_RECEIVED) because if (stat & DW_IC_INTR_RX_FULL). t4: ISR with both IC_INTR_STOP_DET and the 2nd IC_INTR_RX_FULL. t5: Clear listed IC_INTR bits by i2c_dw_read_clear_intrbits_slave(). The current IC_INTR_STOP_DET is cleared by this i2c_dw_read_clear_intrbits_slave(). t6: Enter i2c_dw_irq_handler_slave() and then do i2c_slave_event(WRITE_RECEIVED) because if (stat & DW_IC_INTR_RX_FULL). t7: i2c_slave_event(STOP) never be done because IC_INTR_STOP_DET was cleared in t5. In order to resolve these problems, i2c_dw_read_clear_intrbits_slave() should be called only one time in ISR and take the returned stat to handle those occurred events. Signed-off-by: Michael Wu --- drivers/i2c/busses/i2c-designware-slave.c | 79 --- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c index 44974b53a626..8b3047fb2eae 100644 --- a/drivers/i2c/busses/i2c-designware-slave.c +++ b/drivers/i2c/busses/i2c-designware-slave.c @@ -159,7 +159,6 @@ static int i2c_dw_irq_handler_slave(struct dw_i2c_dev *dev) u32 raw_stat, stat, enabled, tmp; u8 val = 0, slave_activity; - regmap_read(dev->map, DW_IC_INTR_STAT, &stat); regmap_read(dev->map, DW_IC_ENABLE, &enabled); regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &raw_stat); regmap_read(dev->map, DW_IC_STATUS, &tmp); @@ -168,58 +167,61 @@ static int i2c_dw_irq_handler_slave(struct dw_i2c_dev *dev) if (!enabled || !(raw_stat & ~DW_IC_INTR_ACTIVITY) || !dev->slave) return 0; + stat = i2c_dw_read_clear_intrbits_slave(dev); dev_dbg(dev->dev, "%#x STATUS SLAVE_ACTIVITY=%#x : RAW_INTR_STAT=%#x : INTR_STAT=%#x\n", enabled, slave_activity, raw_stat, stat); - if ((stat & DW_IC_INTR_RX_FULL) && (stat & DW_IC_INTR_STOP_DET)) - i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, &val); + if (stat & DW_IC_INTR_RX_FULL) { + if (dev->status != STATUS_WRITE_IN_PROGRESS) { + if (dev->status != STATUS_IDLE) +
[tip:auto-latest] BUILD SUCCESS f1fd159ac6fa12cc197caae397b36060f41cacef
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/peterz/queue.git auto-latest branch HEAD: f1fd159ac6fa12cc197caae397b36060f41cacef Merge branch 'core/rcu' elapsed time: 1230m configs tested: 151 configs skipped: 2 The following configs have been built successfully. More configs may be tested in the coming days. gcc tested configs: arm defconfig arm64allyesconfig arm64 defconfig arm allyesconfig arm allmodconfig sh polaris_defconfig powerpc allyesconfig mipsmaltaup_xpa_defconfig powerpc mpc83xx_defconfig powerpc mpc837x_mds_defconfig powerpc tqm5200_defconfig arc nps_defconfig arm versatile_defconfig powerpcmpc7448_hpc2_defconfig mipsomega2p_defconfig arm stm32_defconfig shmigor_defconfig arm orion5x_defconfig arc nsimosci_hs_defconfig armspear3xx_defconfig armvt8500_v6_v7_defconfig mips rt305x_defconfig armkeystone_defconfig m68k sun3_defconfig powerpc stx_gp3_defconfig sh rsk7203_defconfig powerpc powernv_defconfig shedosk7760_defconfig armmvebu_v7_defconfig sh se7619_defconfig m68k atari_defconfig arm cns3420vb_defconfig xtensa defconfig sh ecovec24_defconfig m68k multi_defconfig powerpc holly_defconfig mips capcella_defconfig powerpc katmai_defconfig armhisi_defconfig arm iop32x_defconfig powerpc mgcoge_defconfig arm zx_defconfig powerpc currituck_defconfig xtensa alldefconfig microblaze mmu_defconfig sh rts7751r2d1_defconfig mips pnx8335_stb225_defconfig sparc sparc32_defconfig powerpcicon_defconfig powerpc mpc836x_rdk_defconfig arm axm55xx_defconfig arm aspeed_g5_defconfig shecovec24-romimage_defconfig mips mpc30x_defconfig arc haps_hs_smp_defconfig sh alldefconfig powerpc g5_defconfig riscvnommu_virt_defconfig m68kmac_defconfig microblaze defconfig ia64 allmodconfig ia64defconfig ia64 allyesconfig m68k allmodconfig m68kdefconfig m68k allyesconfig nios2 defconfig arc allyesconfig nds32 allnoconfig c6x allyesconfig nds32 defconfig nios2allyesconfig cskydefconfig alpha defconfig alphaallyesconfig xtensa allyesconfig h8300allyesconfig arc defconfig sh allmodconfig parisc defconfig s390 allyesconfig parisc allyesconfig s390defconfig i386 allyesconfig sparcallyesconfig sparc defconfig i386defconfig mips allyesconfig mips allmodconfig powerpc allmodconfig powerpc allnoconfig x86_64 randconfig-a004-20201013 x86_64 randconfig-a002-20201013 x86_64 randconfig-a006-20201013 x86_64 randconfig-a001-20201013 x86_64 randconfig-a003-20201013 x86_64 randconfig-a005-20201013 i386 randconfig-a005-20201014 i386 randconfig-a006-20201014 i386 randconfig-a001-20201014 i386 randconfig-a00
RE: [PATCH 1/1] clk: aspeed: modify some default clks are critical
> -Original Message- > From: Joel Stanley > Sent: Wednesday, October 14, 2020 1:28 PM > To: Stephen Boyd > Cc: Andrew Jeffery ; Michael Turquette > ; Ryan Chen ; > BMC-SW ; Linux ARM > ; linux-aspeed > ; linux-...@vger.kernel.org; Linux Kernel > Mailing List > Subject: Re: [PATCH 1/1] clk: aspeed: modify some default clks are critical > > On Wed, 14 Oct 2020 at 02:50, Stephen Boyd wrote: > > > > Quoting Ryan Chen (2020-09-28 00:01:08) > > > In ASPEED SoC LCLK is LPC clock for all SuperIO device, UART1/UART2 > > > are default for Host SuperIO UART device, eSPI clk for Host eSPI bus > > > access eSPI slave channel, those clks can't be disable should keep > > > default, otherwise will affect Host side access SuperIO and SPI slave > > > device. > > > > > > Signed-off-by: Ryan Chen > > > --- > > > > Is there resolution on this thread? > > Not yet. > > We have a system where the BMC (management controller) controls some > clocks, but the peripherals that it's clocking are outside the BMC's control. > In > this case, the host processor us using some UARTs and what not independent of > any code running on the BMC. > > Ryan wants to have them marked as critical so the BMC never powers them > down. > > However, there are systems that don't use this part of the soc, so for those > implementations they are not critical and Linux on the BMC can turn them off. > Take an example, conflict thought about ASPEED_CLK_GATE_BCLK is CLK_IS_CRITICAL in clk-ast2600.c In my opinion, the driver should keep the SoC default clk setting. It is original chip feature. > Do you have any thoughts? Has anyone solved a similar problem already? >
[GIT PULL] xen: branch for v5.10-rc1
Linus, Please git pull the following tag: git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip.git for-linus-5.10b-rc1-tag xen: branch for v5.10-rc1 It contains: - 2 small cleanup patches - A fix for avoiding error messages when initializing MCA banks in a Xen dom0 - A small series for converting the Xen gntdev driver to use pin_user_pages*() instead of get_user_pages*() - An intermediate fix for running as a Xen guest on Arm with KPTI enabled (the final solution will need a new Xen functionality) Thanks. Juergen arch/arm/include/asm/xen/page.h | 5 + arch/arm/xen/enlighten.c | 6 -- arch/arm64/include/asm/xen/page.h | 6 ++ arch/x86/xen/enlighten_pv.c | 9 + arch/x86/xen/mmu_pv.c | 2 +- drivers/xen/gntdev.c | 17 + drivers/xen/pvcalls-front.c | 2 +- 7 files changed, 35 insertions(+), 12 deletions(-) Hui Su (1): x86/xen: Fix typo in xen_pagetable_p2m_free() Jing Xiangfeng (1): xen: remove redundant initialization of variable ret Juergen Gross (1): x86/xen: disable Firmware First mode for correctable memory errors Souptick Joarder (2): xen/gntdev.c: Mark pages as dirty xen/gntdev.c: Convert get_user_pages*() to pin_user_pages*() Stefano Stabellini (1): xen/arm: do not setup the runstate info page if kpti is enabled
Re: [External] Re: [PATCH] mm: proc: add Sock to /proc/meminfo
On Tue, Oct 13, 2020 at 08:21:13AM -0700, Randy Dunlap wrote: > On 10/13/20 8:12 AM, Mike Rapoport wrote: > > On Tue, Oct 13, 2020 at 07:43:59AM -0700, Randy Dunlap wrote: > >> On 10/13/20 1:09 AM, Mike Rapoport wrote: > >>> On Mon, Oct 12, 2020 at 05:53:01PM +0800, Muchun Song wrote: > On Mon, Oct 12, 2020 at 5:24 PM Eric Dumazet > wrote: > > > > On 10/12/20 10:39 AM, Muchun Song wrote: > >> On Mon, Oct 12, 2020 at 3:42 PM Eric Dumazet > >> wrote: > > We are not complaining about TCP using too much memory, but how do > we know that TCP uses a lot of memory. When I firstly face this problem, > I do not know who uses the 25GB memory and it is not shown in the > /proc/meminfo. > If we can know the amount memory of the socket buffer via /proc/meminfo, > we > may not need to spend a lot of time troubleshooting this problem. Not > everyone > knows that a lot of memory may be used here. But I believe many people > should know /proc/meminfo to confirm memory users. > >>> > >>> If I undestand correctly, the problem you are trying to solve is to > >>> simplify troubleshooting of memory usage for people who may not be aware > >>> that networking stack can be a large memory consumer. > >>> > >>> For that a paragraph in 'man 5 proc' maybe a good start: > >>> > >>> >From ddbcf38576d1a2b0e36fe25a27350d566759b664 Mon Sep 17 00:00:00 2001 > >>> From: Mike Rapoport > >>> Date: Tue, 13 Oct 2020 11:07:35 +0300 > >>> Subject: [PATCH] proc.5: meminfo: add not anout network stack memory > >>> consumption > >>> > >>> Signed-off-by: Mike Rapoport > >>> --- > >>> man5/proc.5 | 8 > >>> 1 file changed, 8 insertions(+) > >>> > >>> diff --git a/man5/proc.5 b/man5/proc.5 > >>> index ed309380b..8414676f1 100644 > >>> --- a/man5/proc.5 > >>> +++ b/man5/proc.5 > >>> @@ -3478,6 +3478,14 @@ Except as noted below, > >>> all of the fields have been present since at least Linux 2.6.0. > >>> Some fields are displayed only if the kernel was configured > >>> with various options; those dependencies are noted in the list. > >>> +.IP > >>> +Note that significant part of memory allocated by the network stack > >>> +is not accounted in the file. > >>> +The memory consumption of the network stack can be queried > >>> +using > >>> +.IR /proc/net/sockstat > >>> +or > >>> +.BR ss (8) > >>> .RS > >>> .TP > >>> .IR MemTotal " %lu" > >> > >> Hi Mike, > >> > >> Could you tell us what units those values are in? > >> or is that already explained somewhere else? > > > > It is described a few lines above and anyway, "MemTotal" is a part of > > the diff context ;-) > > with no units AFAICT. > > But I was unclear. I wasn't referring to /proc/meminfo, but instead > to /proc/net/sockstat and its units: > > sockets: used 1224 > TCP: inuse 11 orphan 1 tw 1 alloc 26 mem 3 > UDP: inuse 4 mem 2 > UDPLITE: inuse 0 > RAW: inuse 0 > FRAG: inuse 0 memory 0 > > E.g., for TCP and UDP, are those socket counts or some unit of memory? > If units of memory, what unit size? Ah, these are in 4k pages, AFAIU. And, as it seems /proc/net/sockstat lacks a description in proc.5 at all... > thanks. > -- > ~Randy > > -- Sincerely yours, Mike.
[PATCH v2] x86/unwind/orc: fix inactive tasks with stack pointer in %sp
gcc 10 optimizes the scheduler code differently than its predecessors. When DEBUG_SECTION_MISMATCH config is enabled, Makefile forces gcc not to inline some functions (-fno-inline-functions-called-once). Before gcc 10, "no-inlined" __schedule starts with the usual prologue (push %bp; mov %sp,%bp). So ORC unwinder simply picks stack pointer from %bp and unwinds from __schedule just perfectly: $ cat /proc/1/stack [<0>] ep_poll+0x3e9/0x450 [<0>] do_epoll_wait+0xaa/0xc0 [<0>] __x64_sys_epoll_wait+0x1a/0x20 [<0>] do_syscall_64+0x33/0x40 [<0>] entry_SYSCALL_64_after_hwframe+0x44/0xa9 But now, with gcc 10, there is no %bp prologue in __schedule: $ cat /proc/1/stack The orc entry of the point in __schedule is: sp:sp+88 bp:last_sp-48 type:call end:0 In this case, nobody subtracts sizeof "struct inactive_task_frame" in __unwind_start. The struct is put on the stack by __switch_to_asm and only then __switch_to_asm stores %sp to task->thread.sp. But we start unwinding from a point in __schedule (stored in frame->ret_addr by 'call') and not in __switch_to_asm. So for these example values in __unwind_start: sp=94b50001fdc8 bp=8e1f41d29340 ip=__schedule+0x1f0 The stack is: 94b50001fdc8: 8e1f41578000 # struct inactive_task_frame 94b50001fdd0: 94b50001fdd8: 8e1f41d29340 94b50001fde0: 8e1f41611d40 # ... 94b50001fde8: 93c41920 # bx 94b50001fdf0: 8e1f41d29340 # bp 94b50001fdf8: 9376cad0 # ret_addr (and end of the struct) 0x9376cad0 is __schedule+0x1f0 (after the call to __switch_to_asm). Now follow those 88 bytes from the ORC entry (sp+88). The entry is correct, __schedule really pushes 48 bytes (8*7) + 32 bytes via subq to store some local values (like 4U below). So to unwind, look at the offset 88-sizeof(long) = 0x50 from here: 94b50001fe00: 8e1f41578618 94b50001fe08: 0cc00255 94b50001fe10: 00050004 94b50001fe18: 7793fab6956b2d00 # NOTE (see below) 94b50001fe20: 8e1f41578000 94b50001fe28: 8e1f41578000 94b50001fe30: 8e1f41578000 94b50001fe38: 8e1f41578000 94b50001fe40: 94b50001fed8 94b50001fe48: 8e1f41577ff0 94b50001fe50: 9376cf12 Here is the correct ret addr from __schedule. It translates to schedule+0x42 (insn after a call to __schedule). BUT, unwind_next_frame tries to take the address starting from 0x94b50001fdc8. That is exactly from thread.sp+88-sizeof(long) = 0x94b50001fdc8+88-8 = 0x94b50001fe18, which is garbage marked as NOTE above. So this quits the unwinding as 7793fab6956b2d00 is obviously not a kernel address. There was a fix to skip 'struct inactive_task_frame' in unwind_get_return_address_ptr in commit 187b96db5ca7 ("x86/unwind/orc: Fix unwind_get_return_address_ptr() for inactive tasks"). But we need to skip the struct already in the unwinder proper. So subtract the size (increase the stack pointer) of the structure in __unwind_start directly. This allows for removal of the code added by commit 187b96db5ca7 completely, as the address is now at '(unsigned long *)state->sp - 1', the same as in the generic case. Fixes: ee9f8fce9964 ("x86/unwind: Add the ORC unwinder") Bug: https://bugzilla.suse.com/show_bug.cgi?id=1176907 Signed-off-by: Jiri Slaby Cc: Miroslav Benes Cc: Josh Poimboeuf Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: "H. Peter Anvin" Cc: x...@kernel.org Cc: live-patch...@vger.kernel.org --- [v2] * Remove comment from __unwind_start. * Cc more parties * Polish the commitlog arch/x86/kernel/unwind_orc.c | 9 + 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c index 6a339ce328e0..73f800100066 100644 --- a/arch/x86/kernel/unwind_orc.c +++ b/arch/x86/kernel/unwind_orc.c @@ -321,19 +321,12 @@ EXPORT_SYMBOL_GPL(unwind_get_return_address); unsigned long *unwind_get_return_address_ptr(struct unwind_state *state) { - struct task_struct *task = state->task; - if (unwind_done(state)) return NULL; if (state->regs) return &state->regs->ip; - if (task != current && state->sp == task->thread.sp) { - struct inactive_task_frame *frame = (void *)task->thread.sp; - return &frame->ret_addr; - } - if (state->sp) return (unsigned long *)state->sp - 1; @@ -663,7 +656,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task, } else { struct inactive_task_frame *frame = (void *)task->thread.sp; - state->sp = task->thread.sp; + state->sp = task->thread.sp + sizeof(*frame); state->bp = READ_ONCE_NOCHECK(frame->bp); state->ip = READ_ONCE_NOCHECK(frame->ret_addr); state->signal = (void *)state->ip == ret_from_fork;
Re: disabling CONFIG_LED_CLASS
On 14-10-2020 07:07, Randy Dunlap wrote: > On 10/13/20 9:56 PM, Udo van den Heuvel wrote: >> I.e.: it looks like I will lose some funcionality when I disable >> SND_HDA_CODEC_REALTEK. > > OK. At present you can't have it both ways, i.e., SND_HDA_CODEC_REALTEK > with no LEDS. That driver apparently wants LEDS. Thanks but why have I gone for years without LEDS? I do not need LEDS, I do not want LEDS, I do not have LEDS (that are visible, usable, etc). Please make this selectable instead of forcing more bulk into my kernel. Kind regards, Udo
Re: [PATCH] x86/unwind/orc: fix inactive tasks with sp in sp
On 07. 10. 20, 16:54, Josh Poimboeuf wrote: -ENOPARSE on $SUBJECT. Also please address it to x...@kernel.org, I think the tip maintainers can pick up the fix directly. Hmm, weird, I must have sent an older version as my current patch in the tree has: Cc: Miroslav Benes Cc: Josh Poimboeuf Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: "H. Peter Anvin" Cc: x...@kernel.org Also it might be a good idea to Cc the live-patching mailing list, I presume this causes a livepatch stall? On Wed, Oct 07, 2020 at 10:19:09AM +0200, Jiri Slaby wrote: gcc-10 optimizes the scheduler code differently than its predecessors, depending on DEBUG_SECTION_MISMATCH=y config -- the config sets -fno-inline-functions-called-once. Weird. Was GCC ignoring this flag before? gcc 7 generated the earlier mentioned prologue (push bp; mov sp,bp). So we extract stack pointer from bp. gcc 10 no longer generates the prologue in some of the standalone functions. That's the difference. So we started extracting stack pointer from sp which contains more than we expect. And the problem also (obviously) dismisses when gcc (even 10) inlines the function. @@ -663,7 +656,13 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task, } else { struct inactive_task_frame *frame = (void *)task->thread.sp; - state->sp = task->thread.sp; + /* +* @ret_addr is in __schedule _before_ the @frame is pushed to +* the stack, but @thread.sp is saved in __switch_to_asm only +* _after_ saving the @frame, so subtract the @frame size, i.e. +* add it to @thread.sp. +*/ + state->sp = task->thread.sp + sizeof(*frame); IMO, the code speaks for itself and the comment may be superfluous. Otherwise it looks good to me. Thanks for fixing it! OK, will resend the correct and fixed version. thanks, -- js suse labs
Re: [PATCH] arm64/mm: Validate hotplug range before creating linear mapping
On 10/12/2020 12:59 PM, Ard Biesheuvel wrote: > On Tue, 6 Oct 2020 at 08:36, Anshuman Khandual > wrote: >> >> >> >> On 09/30/2020 01:32 PM, Anshuman Khandual wrote: >>> But if __is_lm_address() checks against the effective linear range instead >>> i.e [_PAGE_OFFSET(vabits_actual)..(PAGE_END - 1)], it can be used for hot >>> plug physical range check there after. Perhaps something like this, though >>> not tested properly. >>> >>> diff --git a/arch/arm64/include/asm/memory.h >>> b/arch/arm64/include/asm/memory.h >>> index afa722504bfd..6da046b479d4 100644 >>> --- a/arch/arm64/include/asm/memory.h >>> +++ b/arch/arm64/include/asm/memory.h >>> @@ -238,7 +238,10 @@ static inline const void *__tag_set(const void *addr, >>> u8 tag) >>> * space. Testing the top bit for the start of the region is a >>> * sufficient check and avoids having to worry about the tag. >>> */ >>> -#define __is_lm_address(addr) (!(((u64)addr) & BIT(vabits_actual - 1))) >>> +static inline bool __is_lm_address(unsigned long addr) >>> +{ >>> + return ((addr >= _PAGE_OFFSET(vabits_actual)) && (addr <= (PAGE_END >>> - 1))); >>> +} >>> >>> #define __lm_to_phys(addr) (((addr) + physvirt_offset)) >>> #define __kimg_to_phys(addr) ((addr) - kimage_voffset) >>> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c >>> index d59ffabb9c84..5750370a7e8c 100644 >>> --- a/arch/arm64/mm/mmu.c >>> +++ b/arch/arm64/mm/mmu.c >>> @@ -1451,8 +1451,7 @@ static bool inside_linear_region(u64 start, u64 size) >>> * address range mapped by the linear map, the start address should >>> * be calculated using vabits_actual. >>> */ >>> - return ((start >= __pa(_PAGE_OFFSET(vabits_actual))) >>> - && ((start + size) <= __pa(PAGE_END - 1))); >>> + return __is_lm_address(__va(start)) && __is_lm_address(__va(start + >>> size)); >>> } >>> >>> int arch_add_memory(int nid, u64 start, u64 size, >> >> Will/Ard, >> >> Any thoughts about this ? __is_lm_address() now checks for a range instead >> of a bit. This will be compatible later on, even if linear mapping range >> changes from current lower half scheme. >> > > As I'm sure you have noticed, I sent out some patches that get rid of > physvirt_offset, and which simplify __is_lm_address() to only take > compile time constants into account (unless KASAN is enabled). This > means that in the 52-bit VA case, __is_lm_address() does not > distinguish between virtual addresses that can be mapped by the > hardware and ones that cannot. Yeah, though was bit late in getting to the series. So with that change there might be areas in the linear mapping which cannot be addressed by the hardware and hence should also need be checked apart from proposed linear mapping coverage test, during memory hotplug ? > > In the memory hotplug case, we need to decide whether the added memory > will appear in the addressable area, which is a different question. So > it makes sense to duplicate some of the logic that exists in > arm64_memblock_init() (or factor it out) to decide whether this newly > added memory will appear in the addressable window or not. It seems unlikely that any hotplug agent (e.g. firmware) will ever push through a memory range which is not accessible in the hardware but then it is not impossible either. In summary, arch_add_memory() should check 1. Range can be covered inside linear mapping 2. Range is accessible by the hardware Before the VA space organization series, (2) was not necessary as it was contained inside (1) ? > > So I think your original approach makes more sense here, although I > think you want '(start + size - 1) <= __pa(PAGE_END - 1)' in the > comparison above (and please drop the redundant parens) > Sure, will accommodate these changes.
[PATCH] Add support for mv88e6393x family of Marvell.
The Marvell 88E6393X device is a single-chip integration of a 11-port Ethernet switch with eight integrated Gigabit Ethernet (GbE) transceivers and three 10-Gigabit interfaces. This patch adds functionalities specific to mv88e6393x family (88E6393X, 88E6193X and 88E6191X) Signed-off-by: Pavana Sharma --- drivers/net/dsa/mv88e6xxx/chip.c| 90 + drivers/net/dsa/mv88e6xxx/chip.h| 2 + drivers/net/dsa/mv88e6xxx/global1.h | 2 + drivers/net/dsa/mv88e6xxx/global2.c | 7 + drivers/net/dsa/mv88e6xxx/global2.h | 8 + drivers/net/dsa/mv88e6xxx/port.c| 302 drivers/net/dsa/mv88e6xxx/port.h| 39 +++- drivers/net/dsa/mv88e6xxx/serdes.c | 242 ++ drivers/net/dsa/mv88e6xxx/serdes.h | 39 9 files changed, 730 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index f0dbc05e30a4..241ff788b0b1 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -634,6 +634,23 @@ static void mv88e6390x_phylink_validate(struct mv88e6xxx_chip *chip, int port, mv88e6390_phylink_validate(chip, port, mask, state); } +static void mv88e6393x_phylink_validate(struct mv88e6xxx_chip *chip, int port, + unsigned long *mask, + struct phylink_link_state *state) +{ + if (port == 0 || port >= 9) { + phylink_set(mask, 1baseT_Full); + phylink_set(mask, 1baseKR_Full); + phylink_set(mask, 2500baseX_Full); + phylink_set(mask, 2500baseT_Full); + } + + phylink_set(mask, 1000baseT_Full); + phylink_set(mask, 1000baseX_Full); + + mv88e6065_phylink_validate(chip, port, mask, state); +} + static void mv88e6xxx_validate(struct dsa_switch *ds, int port, unsigned long *supported, struct phylink_link_state *state) @@ -4141,6 +4158,56 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { .phylink_validate = mv88e6390_phylink_validate, }; +static const struct mv88e6xxx_ops mv88e6193x_ops = { + /* MV88E6XXX_FAMILY_6393X */ + .setup_errata = mv88e6393x_setup_errata, + .irl_init_all = mv88e6390_g2_irl_init_all, + .get_eeprom = mv88e6xxx_g2_get_eeprom8, + .set_eeprom = mv88e6xxx_g2_set_eeprom8, + .set_switch_mac = mv88e6xxx_g2_set_switch_mac, + .phy_read = mv88e6xxx_g2_smi_phy_read, + .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, + .port_set_speed_duplex = mv88e6393x_port_set_speed_duplex, + .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, + .port_tag_remap = mv88e6390_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ether_type = mv88e6393x_port_set_ether_type, + .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, + .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, + .port_pause_limit = mv88e6390_port_pause_limit, + .port_set_cmode = mv88e6393x_port_set_cmode, + .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, + .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, + .port_get_cmode = mv88e6352_port_get_cmode, + .stats_snapshot = mv88e6390_g1_stats_snapshot, + .stats_set_histogram = mv88e6390_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6320_stats_get_sset_count, + .stats_get_strings = mv88e6320_stats_get_strings, + .stats_get_stats = mv88e6390_stats_get_stats, + .set_cpu_port = mv88e6393x_port_set_cpu_dest, + .set_egress_port = mv88e6393x_set_egress_port, + .watchdog_ops = &mv88e6390_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6393x_port_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, + .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6390_g1_rmu_disable, + .vtu_getnext = mv88e6390_g1_vtu_getnext, + .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, + .serdes_power = mv88e6393x_serdes_power, + .serdes_get_lane = mv88e6393x_serdes_get_lane, + /* Check status register pause & lpa register */ + .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state, + .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, + .serdes_irq_enable = mv88e6393x_serdes_irq_enable, + .serdes_irq_status = mv88e6393x_serdes_irq_status, + .gpio_ops = &mv88e6352_gpio_ops, + .avb_ops = &mv88e6390_avb_ops, + .ptp_ops = &mv88e6352_ptp_ops, + .phylink_validate = mv88e6393x_phylink_validate, +}; + static const struct mv88e6xxx_ops mv88e6240_ops = { /* MV88E6XXX_FAMILY_6352 */ .ieee_pri_map = mv88e6085_g1_ieee_pri_map, @@ -5073,6 +5140,29 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] =
Re: disabling CONFIG_LED_CLASS
On 14-10-2020 06:49, Randy Dunlap wrote: > If you disable SND_HDA_CODEC_REALTEK, then the rest of the > LED kconfig symbols can be disabled. Sure, but: # dmesg|grep audi (...) [ 19.971537] snd_hda_codec_generic hdaudioC0D0: ignore pin 0x7, too many assigned pins [ 19.973547] snd_hda_codec_generic hdaudioC0D0: autoconfig for Generic: line_outs=0 (0x0/0x0/0x0/0x0/0x0) type:line [ 19.975642] snd_hda_codec_generic hdaudioC0D0:speaker_outs=0 (0x0/0x0/0x0/0x0/0x0) [ 19.94] snd_hda_codec_generic hdaudioC0D0:hp_outs=0 (0x0/0x0/0x0/0x0/0x0) [ 19.980176] snd_hda_codec_generic hdaudioC0D0:mono: mono_out=0x0 [ 19.982257] snd_hda_codec_generic hdaudioC0D0:dig-out=0x3/0x5 [ 19.984412] snd_hda_codec_generic hdaudioC0D0:inputs: [ 20.035088] snd_hda_codec_realtek hdaudioC1D0: autoconfig for ALC1220: line_outs=3 (0x14/0x15/0x16/0x0/0x0) type:line [ 20.036940] snd_hda_codec_realtek hdaudioC1D0:speaker_outs=0 (0x0/0x0/0x0/0x0/0x0) [ 20.039579] snd_hda_codec_realtek hdaudioC1D0:hp_outs=1 (0x1b/0x0/0x0/0x0/0x0) [ 20.041690] snd_hda_codec_realtek hdaudioC1D0:mono: mono_out=0x0 [ 20.044076] snd_hda_codec_realtek hdaudioC1D0:dig-out=0x1e/0x0 [ 20.046173] snd_hda_codec_realtek hdaudioC1D0:inputs: [ 20.049252] snd_hda_codec_realtek hdaudioC1D0: Front Mic=0x19 [ 20.051287] snd_hda_codec_realtek hdaudioC1D0: Rear Mic=0x18 [ 20.053084] snd_hda_codec_realtek hdaudioC1D0: Line=0x1a [ 20.427487] usbcore: registered new interface driver snd-usb-audio I.e.: it looks like I will lose some funcionality when I disable SND_HDA_CODEC_REALTEK. Kind regards, Udo
Re: [PATCH v2 4/8] dt-bindings: phy: convert HDMI PHY binding to YAML schema
Hi, Chunfeng: On Tue, 2020-10-13 at 16:52 +0800, Chunfeng Yun wrote: > Convert HDMI PHY binding to YAML schema mediatek,ufs-phy.yaml > > Signed-off-by: Chunfeng Yun > --- > v2: fix binding check warning of reg in example > --- > .../display/mediatek/mediatek,hdmi.txt| 17 +--- > .../bindings/phy/mediatek,hdmi-phy.yaml | 90 +++ > 2 files changed, 91 insertions(+), 16 deletions(-) > create mode 100644 > Documentation/devicetree/bindings/phy/mediatek,hdmi-phy.yaml > > diff --git > a/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.txt > b/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.txt > index 7b124242b0c5..edac18951a75 100644 > --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.txt > +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.txt > @@ -50,22 +50,7 @@ Required properties: > > HDMI PHY > > - > -The HDMI PHY serializes the HDMI encoder's three channel 10-bit parallel > -output and drives the HDMI pads. > - > -Required properties: > -- compatible: "mediatek,-hdmi-phy" > -- reg: Physical base address and length of the module's registers > -- clocks: PLL reference clock > -- clock-names: must contain "pll_ref" > -- clock-output-names: must be "hdmitx_dig_cts" on mt8173 > -- #phy-cells: must be <0> > -- #clock-cells: must be <0> > - > -Optional properties: > -- mediatek,ibias: TX DRV bias current for <1.65Gbps, defaults to 0xa > -- mediatek,ibias_up: TX DRV bias current for >1.65Gbps, defaults to 0x1c > +See phy/mediatek,hdmi-phy.yaml > > Example: > > diff --git a/Documentation/devicetree/bindings/phy/mediatek,hdmi-phy.yaml > b/Documentation/devicetree/bindings/phy/mediatek,hdmi-phy.yaml > new file mode 100644 > index ..77df50204606 > --- /dev/null > +++ b/Documentation/devicetree/bindings/phy/mediatek,hdmi-phy.yaml > @@ -0,0 +1,90 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +# Copyright (c) 2020 MediaTek > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/phy/mediatek,hdmi-phy.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: MediaTek High Definition Multimedia Interface (HDMI) PHY binding > + > +maintainers: > + - CK Hu I think you should remove "CK Hu " and add latest mediatek drm maintainer: DRM DRIVERS FOR MEDIATEK M: Chun-Kuang Hu M: Philipp Zabel L: dri-de...@lists.freedesktop.org S: Supported F: Documentation/devicetree/bindings/display/mediatek/ F: drivers/gpu/drm/mediatek/ Regards, CK > + - Chunfeng Yun > + > +description: | > + The HDMI PHY serializes the HDMI encoder's three channel 10-bit parallel > + output and drives the HDMI pads. > + > +properties: > + $nodename: > +pattern: "^hdmi-phy@[0-9a-f]+$" > + > + compatible: > +enum: > + - mediatek,mt2701-hdmi-phy > + - mediatek,mt8173-hdmi-phy > + > + reg: > +maxItems: 1 > + > + clocks: > +items: > + - description: PLL reference clock > + > + clock-names: > +items: > + - const: pll_ref > + > + clock-output-names: > +items: > + - const: hdmitx_dig_cts > + > + "#phy-cells": > +const: 0 > + > + "#clock-cells": > +const: 0 > + > + mediatek,ibias: > +description: > + TX DRV bias current for < 1.65Gbps > +$ref: /schemas/types.yaml#/definitions/uint32 > +minimum: 0 > +maximum: 63 > +default: 0xa > + > + mediatek,ibias_up: > +description: > + TX DRV bias current for >= 1.65Gbps > +$ref: /schemas/types.yaml#/definitions/uint32 > +minimum: 0 > +maximum: 63 > +default: 0x1c > + > +required: > + - compatible > + - reg > + - clocks > + - clock-names > + - clock-output-names > + - "#phy-cells" > + - "#clock-cells" > + > +additionalProperties: false > + > +examples: > + - | > +#include > +hdmi_phy: hdmi-phy@10209100 { > +compatible = "mediatek,mt8173-hdmi-phy"; > +reg = <0x10209100 0x24>; > +clocks = <&apmixedsys CLK_APMIXED_HDMI_REF>; > +clock-names = "pll_ref"; > +clock-output-names = "hdmitx_dig_cts"; > +mediatek,ibias = <0xa>; > +mediatek,ibias_up = <0x1c>; > +#clock-cells = <0>; > +#phy-cells = <0>; > +}; > + > +...
Re: [PATCH] DMA: PL330: Remove unreachable code
On 13-10-20, 17:17, Surendran K wrote: > _setup_req(..) never returns negative value. > Hence the condition ret < 0 is never met The subsystem is "dmaengine", git log would tell you the tags to use > > Signed-off-by: Surendran K > --- > drivers/dma/pl330.c | 2 -- > 1 file changed, 2 deletions(-) > > diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c > index e9f0101d92fa..8355586c9788 100644 > --- a/drivers/dma/pl330.c > +++ b/drivers/dma/pl330.c > @@ -1527,8 +1527,6 @@ static int pl330_submit_req(struct pl330_thread *thrd, > > /* First dry run to check if req is acceptable */ > ret = _setup_req(pl330, 1, thrd, idx, &xs); > - if (ret < 0) > - goto xfer_exit; > > if (ret > pl330->mcbufsz / 2) { > dev_info(pl330->ddma.dev, "%s:%d Try increasing mcbufsz > (%i/%i)\n", > -- > 2.17.1 -- ~Vinod
Re: disabling CONFIG_LED_CLASS
On 13-10-2020 18:03, Randy Dunlap wrote: > On 10/13/20 8:53 AM, Randy Dunlap wrote: >> [adding LED people + list] >> >> On 10/13/20 6:24 AM, Udo van den Heuvel wrote: (...) So how do I disable this stuff? > > I was able to disable LEDS_CLASS and NEW_LEDS after I disabled the following > config symbols: > > > --- xx64/config-def64 2020-10-13 08:53:56.050501724 -0700 > +++ xx64/.config 2020-10-13 08:58:12.439205389 -0700 > -CONFIG_MAC80211_LEDS=y > -CONFIG_RFKILL_LEDS=y > -# CONFIG_LED_TRIGGER_PHY is not set > -CONFIG_INPUT_LEDS=y > -# CONFIG_HID_LED is not set > -# CONFIG_USB_LED_TRIG is not set > -# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set > -CONFIG_LEDS_TRIGGERS=y > -CONFIG_EEEPC_LAPTOP=y > +# CONFIG_EEEPC_LAPTOP is not set > > This last one was the biggest problem for me. > I started with x86_64 defconfig. # grep LED .config # grep LEDS .config # grep EEPC .config # make oldconfig (...) * * LED Support * LED Support (NEW_LEDS) [Y/?] (NEW) y LED Class Support (LEDS_CLASS) [M/y/?] (NEW) n So we still are stuck. Udo
GREETINGS....
Dear Beloved Friend, Sorry if this email came to you as a surprise,I am Dr.Dawuda Usman and we are looking for a company or individual from your region to help us receive investment fund .I will send you full details As soon As I hear from you thanks. Yours Faithfully, Dr.Dawuda Usman.
Re: [PATCH 1/2] Asoc: qcom: lpass-cpu: Fix clock disable failure
Thanks Mark Brown for your time !!! On 10/13/2020 8:45 PM, Mark Brown wrote: On Tue, Oct 13, 2020 at 07:09:46PM +0530, Srinivasa Rao Mandadapu wrote: From: V Sujith Kumar Reddy Disable MI2S bit clock from PAUSE/STOP/SUSPEND usecase instead of shutdown time. Acheive this by invoking clk_disable_unprepare API from cpu daiops shutdown to cpu daiops trigger. I'm missing patch 2 here? No.. It's a single patch. By mistake I sent with wrong header. This Fix is update to the below patch. https://lore.kernel.org/patchwork/patch/1308101/ Fixes should be specified using tags like this: Fixes: commit 30fb9454ab23 ("selftests/vm: hmm-tests: remove the libhugetlbfs dependency") in the changelog. Thanks for your guidance. I will take care of it next time. Please submit patches using subject lines reflecting the style for the subsystem, this makes it easier for people to identify relevant patches. Look at what existing commits in the area you're changing are doing and make sure your subject lines visually resemble what they're doing. There's no need to resubmit to fix this alone. -- Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc., is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
Re: [PATCH v3 09/15] arm64: tegra210: XUSB PADCTL add "nvidia,pmc" prop
I will add a dt-bindings commit for this change. Thanks for review. JC On 9/28/20 9:18 PM, Thierry Reding wrote: > On Wed, Sep 09, 2020 at 04:10:35PM +0800, JC Kuo wrote: >> PMC driver provides USB sleepwalk registers access to XUSB PADCTL >> driver. This commit adds a "nvidia,pmc" property which points to >> PMC node to XUSB PADCTL device node. >> >> Signed-off-by: JC Kuo >> --- >> v3: >>no change >> >> arch/arm64/boot/dts/nvidia/tegra210.dtsi | 1 + >> 1 file changed, 1 insertion(+) >> >> diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi >> b/arch/arm64/boot/dts/nvidia/tegra210.dtsi >> index 829f786af133..67c90a0ea32e 100644 >> --- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi >> +++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi >> @@ -1040,6 +1040,7 @@ padctl: padctl@7009f000 { >> reg = <0x0 0x7009f000 0x0 0x1000>; >> resets = <&tegra_car 142>; >> reset-names = "padctl"; >> +nvidia,pmc = <&tegra_pmc>; > > I hadn't noticed before but it looks like the DT bindings haven't been > updated with this new property. > > Thierry >
Re: [PATCH v3 08/15] soc/tegra: pmc: Provide usb sleepwalk register map
I will amend commit accordingly and submit a new patch. Thanks for review. JC On 9/28/20 9:17 PM, Thierry Reding wrote: > On Wed, Sep 09, 2020 at 04:10:34PM +0800, JC Kuo wrote: >> This commit implements a register map which grants USB (UTMI and HSIC) >> sleepwalk registers access to USB PHY drivers. The USB sleepwalk logic >> is in PMC hardware block but USB PHY drivers have the best knowledge >> of proper programming sequence. This approach prevents using custom >> pmc APIs. > > I don't think this final sentence is useful. The commit message should > explain what you're doing, but there's no need to enumerate any other > inferior solution you didn't choose to implement. > > If you do want to keep it: s/pmc/PMC/. > > While at it, perhaps replace "usb" by "USB" in the subject as well. > >> >> Signed-off-by: JC Kuo >> --- >> v3: >>commit message improvement >>drop regmap_reg() usage >>rename 'reg' with 'offset' >>rename 'val' with 'value' >>drop '__force' when invokes devm_regmap_init() >>print error code of devm_regmap_init() >>move devm_regmap_init() a litter bit earlier >>explicitly set '.has_usb_sleepwalk=false' >> >> drivers/soc/tegra/pmc.c | 95 + >> 1 file changed, 95 insertions(+) >> >> diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c >> index d332e5d9abac..ff24891ce9ca 100644 >> --- a/drivers/soc/tegra/pmc.c >> +++ b/drivers/soc/tegra/pmc.c >> @@ -43,6 +43,7 @@ >> #include >> #include >> #include >> +#include >> >> #include >> #include >> @@ -102,6 +103,9 @@ >> >> #define PMC_PWR_DET_VALUE 0xe4 >> >> +#define PMC_USB_DEBOUNCE_DEL0xec >> +#define PMC_USB_AO 0xf0 >> + >> #define PMC_SCRATCH41 0x140 >> >> #define PMC_WAKE2_MASK 0x160 >> @@ -133,6 +137,13 @@ >> #define IO_DPD2_STATUS 0x1c4 >> #define SEL_DPD_TIM 0x1c8 >> >> +#define PMC_UTMIP_UHSIC_TRIGGERS0x1ec >> +#define PMC_UTMIP_UHSIC_SAVED_STATE 0x1f0 >> + >> +#define PMC_UTMIP_TERM_PAD_CFG 0x1f8 >> +#define PMC_UTMIP_UHSIC_SLEEP_CFG 0x1fc >> +#define PMC_UTMIP_UHSIC_FAKE0x218 >> + >> #define PMC_SCRATCH54 0x258 >> #define PMC_SCRATCH54_DATA_SHIFT 8 >> #define PMC_SCRATCH54_ADDR_SHIFT 0 >> @@ -145,8 +156,18 @@ >> #define PMC_SCRATCH55_CHECKSUM_SHIFT 16 >> #define PMC_SCRATCH55_I2CSLV1_SHIFT0 >> >> +#define PMC_UTMIP_UHSIC_LINE_WAKEUP0x26c >> + >> +#define PMC_UTMIP_BIAS_MASTER_CNTRL 0x270 >> +#define PMC_UTMIP_MASTER_CONFIG 0x274 >> +#define PMC_UTMIP_UHSIC2_TRIGGERS 0x27c >> +#define PMC_UTMIP_MASTER2_CONFIG0x29c >> + >> #define GPU_RG_CNTRL0x2d4 >> >> +#define PMC_UTMIP_PAD_CFG0 0x4c0 >> +#define PMC_UTMIP_UHSIC_SLEEP_CFG1 0x4d0 >> +#define PMC_UTMIP_SLEEPWALK_P3 0x4e0 >> /* Tegra186 and later */ >> #define WAKE_AOWAKE_CNTRL(x) (0x000 + ((x) << 2)) >> #define WAKE_AOWAKE_CNTRL_LEVEL (1 << 3) >> @@ -334,6 +355,7 @@ struct tegra_pmc_soc { >> const struct pmc_clk_init_data *pmc_clks_data; >> unsigned int num_pmc_clks; >> bool has_blink_output; >> +bool has_usb_sleepwalk; >> }; >> >> static const char * const tegra186_reset_sources[] = { >> @@ -2495,6 +2517,68 @@ static void tegra_pmc_clock_register(struct tegra_pmc >> *pmc, >> err); >> } >> >> +static const struct regmap_range pmc_usb_sleepwalk_ranges[] = { >> +regmap_reg_range(PMC_USB_DEBOUNCE_DEL, PMC_USB_AO), >> +regmap_reg_range(PMC_UTMIP_UHSIC_TRIGGERS, PMC_UTMIP_UHSIC_SAVED_STATE), >> +regmap_reg_range(PMC_UTMIP_TERM_PAD_CFG, PMC_UTMIP_UHSIC_FAKE), >> +regmap_reg_range(PMC_UTMIP_UHSIC_LINE_WAKEUP, >> PMC_UTMIP_UHSIC_LINE_WAKEUP), >> +regmap_reg_range(PMC_UTMIP_BIAS_MASTER_CNTRL, PMC_UTMIP_MASTER_CONFIG), >> +regmap_reg_range(PMC_UTMIP_UHSIC2_TRIGGERS, PMC_UTMIP_MASTER2_CONFIG), >> +regmap_reg_range(PMC_UTMIP_PAD_CFG0, PMC_UTMIP_UHSIC_SLEEP_CFG1), >> +regmap_reg_range(PMC_UTMIP_SLEEPWALK_P3, PMC_UTMIP_SLEEPWALK_P3), >> +}; >> + >> +static const struct regmap_access_table pmc_usb_sleepwalk_table = { >> +.yes_ranges = pmc_usb_sleepwalk_ranges, >> +.n_yes_ranges = ARRAY_SIZE(pmc_usb_sleepwalk_ranges), >> +}; >> + >> +static int tegra_pmc_regmap_readl(void *context, unsigned int offset, >> unsigned int *value) >> +{ >> +struct tegra_pmc *pmc = context; >> + >> +*value = tegra_pmc_readl(pmc, offset); >> +return 0; >> +} >> + >> +static int tegra_pmc_regmap_writel(void *context, unsigned int offset, >> unsigned int value) >> +{ >> +struct tegra_pmc *pmc = context; >> + >> +tegra_pmc_writel(pmc, value, offset); >> +return 0; >> +} >> + >> +static const struct regmap_config usb_sleepwalk_regmap_config = { >> +.name = "usb_sleepwalk", >> +.reg_bits = 32, >> +.val_bits =
iwlwifi: spaces in procfs filenames ?
commit 64fa3aff89785b5a924ce3934f6595c35b4dffee Author: Sharon Dvir Date: Wed Aug 17 15:35:09 2016 +0300 iwlwifi: pcie: give a meaningful name to interrupt request perhaps unintentionally for file: drivers/net/wireless/intel/iwlwifi/pcie/internal.h in function static inline const char *queue_name creates spaces in procfs filenames. drivers/net/wireless/intel/iwlwifi/pcie/internal.h:static inline const char *queue_name(struct device *dev, drivers/net/wireless/intel/iwlwifi/pcie/internal.h- struct iwl_trans_pcie *trans_p, int i) drivers/net/wireless/intel/iwlwifi/pcie/internal.h-{ drivers/net/wireless/intel/iwlwifi/pcie/internal.h- if (trans_p->shared_vec_mask) { drivers/net/wireless/intel/iwlwifi/pcie/internal.h- int vec = trans_p->shared_vec_mask & drivers/net/wireless/intel/iwlwifi/pcie/internal.h- IWL_SHARED_IRQ_FIRST_RSS ? 1 : 0; drivers/net/wireless/intel/iwlwifi/pcie/internal.h- drivers/net/wireless/intel/iwlwifi/pcie/internal.h- if (i == 0) drivers/net/wireless/intel/iwlwifi/pcie/internal.h- return DRV_NAME ": shared IRQ"; drivers/net/wireless/intel/iwlwifi/pcie/internal.h- drivers/net/wireless/intel/iwlwifi/pcie/internal.h- return devm_kasprintf(dev, GFP_KERNEL, drivers/net/wireless/intel/iwlwifi/pcie/internal.h- DRV_NAME ": queue %d", i + vec); drivers/net/wireless/intel/iwlwifi/pcie/internal.h- } drivers/net/wireless/intel/iwlwifi/pcie/internal.h- if (i == 0) drivers/net/wireless/intel/iwlwifi/pcie/internal.h- return DRV_NAME ": default queue"; drivers/net/wireless/intel/iwlwifi/pcie/internal.h- drivers/net/wireless/intel/iwlwifi/pcie/internal.h- if (i == trans_p->alloc_vecs - 1) drivers/net/wireless/intel/iwlwifi/pcie/internal.h- return DRV_NAME ": exception"; drivers/net/wireless/intel/iwlwifi/pcie/internal.h- drivers/net/wireless/intel/iwlwifi/pcie/internal.h- return devm_kasprintf(dev, GFP_KERNEL, drivers/net/wireless/intel/iwlwifi/pcie/internal.h- DRV_NAME ": queue %d", i); drivers/net/wireless/intel/iwlwifi/pcie/internal.h-} # find /proc/ | grep " " /proc/irq/130/iwlwifi: default queue /proc/irq/131/iwlwifi: queue 1 /proc/irq/132/iwlwifi: queue 2 /proc/irq/133/iwlwifi: queue 3 /proc/irq/134/iwlwifi: queue 4 /proc/irq/135/iwlwifi: exception Can these names be changed back or collapsed to avoid the space use in procfs?
[PATCH] perf: Improve PT documentation slightly
Document the higher level --insn-trace etc. perf script options. Include the howto how to build xed into the manpage Cc: adrian.hun...@intel.com Signed-off-by: Andi Kleen --- tools/perf/Documentation/perf-intel-pt.txt | 30 ++ 1 file changed, 30 insertions(+) diff --git a/tools/perf/Documentation/perf-intel-pt.txt b/tools/perf/Documentation/perf-intel-pt.txt index d5a266d7f15b..cc2a8b2be31a 100644 --- a/tools/perf/Documentation/perf-intel-pt.txt +++ b/tools/perf/Documentation/perf-intel-pt.txt @@ -112,6 +112,32 @@ The flags are "bcrosyiABEx" which stand for branch, call, return, conditional, system, asynchronous, interrupt, transaction abort, trace begin, trace end, and in transaction, respectively. +perf script also supports higher level ways to dump instruction traces: + + perf script --insn-trace --xed + +Dump all instructions. This requires installing the xed tool (see XED below) +Dumping all instructions in a long trace can be fairly slow. It is usually better +to start with higher level decoding, like + + perf script --call-trace + +or + + perf script --call-ret-trace + +and then select a time range of interest. The time range can then be examined +in detail with + + perf script --time starttime,stoptime --insn-trace --xed + +While examining the trace it's also useful to filter on specific CPUs using +the -C option + + perf script --time starttime,stoptime --insn-trace --xed -C 1 + +Dump all instructions in time range on CPU 1. + Another interesting field that is not printed by default is 'ipc' which can be displayed as follows: @@ -1093,6 +1119,10 @@ To display PEBS events from the Intel PT trace, use the itrace 'o' option e.g. perf script --itrace=oe +XED +--- + +include::build-xed.txt[] SEE ALSO -- 2.28.0
[PATCH] perf: Add support for exclusive groups/events
Peter suggested that using the exclusive mode in perf could avoid some problems with bad scheduling of groups. Exclusive is implemented in the kernel, but wasn't exposed by the perf tool, so hard to use without custom low level API users. Add support for marking groups or events with :e for exclusive in the perf tool. The implementation is basically the same as the existing pinned attribute. Cc: pet...@infradead.org Signed-off-by: Andi Kleen --- tools/perf/Documentation/perf-list.txt | 1 + tools/perf/tests/parse-events.c| 58 +- tools/perf/util/parse-events.c | 9 +++- tools/perf/util/parse-events.l | 2 +- 4 files changed, 67 insertions(+), 3 deletions(-) diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt index 10ed539a8859..4c7db1da8fcc 100644 --- a/tools/perf/Documentation/perf-list.txt +++ b/tools/perf/Documentation/perf-list.txt @@ -58,6 +58,7 @@ counted. The following modifiers exist: S - read sample value (PERF_SAMPLE_READ) D - pin the event to the PMU W - group is weak and will fallback to non-group if not schedulable, + e - group or event are exclusive and do not share the PMU The 'p' modifier can be used for specifying how precise the instruction address should be. The 'p' modifier can be specified multiple times: diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 7f9f87a470c3..7411dd4d76cf 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -557,6 +557,7 @@ static int test__checkevent_pmu_events(struct evlist *evlist) TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned); + TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.exclusive); return 0; } @@ -575,6 +576,7 @@ static int test__checkevent_pmu_events_mix(struct evlist *evlist) TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned); + TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.exclusive); /* cpu/pmu-event/u*/ evsel = evsel__next(evsel); @@ -587,6 +589,7 @@ static int test__checkevent_pmu_events_mix(struct evlist *evlist) TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned); + TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.pinned); return 0; } @@ -1277,6 +1280,49 @@ static int test__pinned_group(struct evlist *evlist) return 0; } +static int test__checkevent_exclusive_modifier(struct evlist *evlist) +{ + struct evsel *evsel = evlist__first(evlist); + + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip); + TEST_ASSERT_VAL("wrong exclusive", evsel->core.attr.exclusive); + + return test__checkevent_symbolic_name(evlist); +} + +static int test__exclusive_group(struct evlist *evlist) +{ + struct evsel *evsel, *leader; + + TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->core.nr_entries); + + /* cycles - group leader */ + evsel = leader = evlist__first(evlist); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", + PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong group name", !evsel->group_name); + TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); + TEST_ASSERT_VAL("wrong exclusive", evsel->core.attr.exclusive); + + /* cache-misses - can not be pinned, but will go on with the leader */ + evsel = evsel__next(evsel); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", + PERF_COUNT_HW_CACHE_MISSES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.exclusive); + + /* branch-misses - ditto */ + evsel = evsel__next(evsel); + TEST_ASSERT_VAL("wrong config", + PERF_COUNT_HW_BRANCH_MISSES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.exclusive); + + return 0; +} static int test__checkevent_breakpoint_len(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); @@ -1765,7 +1811,17 @@ static struct evlist_test test__even
Re: [PATCH v2 1/2] extcon: add driver for TI TUSB320
Hi, Looks good to me. I add some comment. Please check them. On 10/12/20 11:47 PM, Michael Auchter wrote: > This patch adds an extcon driver for the TI TUSB320 USB Type-C device. > This can be used to detect whether the port is configured as a > downstream or upstream facing port. > > Signed-off-by: Michael Auchter > --- > Changes since v1: > - Drop license text that's redundant with SPDX tag > - Cleanup, sort list of includes > - Add additional register defines > - Switch to use regmap API > - Fix Kconfig to depend on I2C, not GPIOLIB > > drivers/extcon/Kconfig | 8 ++ > drivers/extcon/Makefile | 1 + > drivers/extcon/extcon-usbc-tusb320.c | 191 +++ > 3 files changed, 200 insertions(+) > create mode 100644 drivers/extcon/extcon-usbc-tusb320.c > > diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig > index aac507bff135..af58ebca2bf6 100644 > --- a/drivers/extcon/Kconfig > +++ b/drivers/extcon/Kconfig > @@ -186,4 +186,12 @@ config EXTCON_USBC_CROS_EC > Say Y here to enable USB Type C cable detection extcon support when > using Chrome OS EC based USB Type-C ports. > > +config EXTCON_USBC_TUSB320 > + tristate "TI TUSB320 USB-C extcon support" > + depends on I2C > + select REGMAP_I2C > + help > + Say Y here to enable support for USB Type C cable detection extcon > + support using a TUSB320. > + > endif > diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile > index 52096fd8a216..fe10a1b7d18b 100644 > --- a/drivers/extcon/Makefile > +++ b/drivers/extcon/Makefile > @@ -25,3 +25,4 @@ obj-$(CONFIG_EXTCON_RT8973A)+= extcon-rt8973a.o > obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o > obj-$(CONFIG_EXTCON_USB_GPIO)+= extcon-usb-gpio.o > obj-$(CONFIG_EXTCON_USBC_CROS_EC) += extcon-usbc-cros-ec.o > +obj-$(CONFIG_EXTCON_USBC_TUSB320) += extcon-usbc-tusb320.o > diff --git a/drivers/extcon/extcon-usbc-tusb320.c > b/drivers/extcon/extcon-usbc-tusb320.c > new file mode 100644 > index ..93f1843ca89b > --- /dev/null > +++ b/drivers/extcon/extcon-usbc-tusb320.c > @@ -0,0 +1,191 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/** > + * drivers/extcon/extcon-tusb320.c - TUSB320 extcon driver > + * > + * Copyright (C) 2020 National Instruments Corporation > + * Author: Michael Auchter > + */ > + > +#include > +#include > +#include > +#include > +#include irq.h doesn't be needed. Better to remove irq.h. > +#include > +#include > +#include > + > +#define TUSB320_REG9 0x9 > +#define TUSB320_REG9_ATTACHED_STATE_SHIFT6 > +#define TUSB320_REG9_ATTACHED_STATE_MASK 0x3 > +#define TUSB320_REG9_CABLE_DIRECTION BIT(5) > +#define TUSB320_REG9_INTERRUPT_STATUSBIT(4) > +#define TUSB320_ATTACHED_STATE_NONE 0x0 > +#define TUSB320_ATTACHED_STATE_DFP 0x1 > +#define TUSB320_ATTACHED_STATE_UFP 0x2 > +#define TUSB320_ATTACHED_STATE_ACC 0x3 Above definition contain the 'space' for indentation. Please edit it as following: -#define TUSB320_ATTACHED_STATE_DFP 0x1 -#define TUSB320_ATTACHED_STATE_UFP 0x2 -#define TUSB320_ATTACHED_STATE_ACC 0x3 +#define TUSB320_ATTACHED_STATE_DFP 0x1 +#define TUSB320_ATTACHED_STATE_UFP 0x2 +#define TUSB320_ATTACHED_STATE_ACC 0x3 > + > +struct tusb320_priv { > + struct device *dev; > + struct regmap *regmap; > + struct extcon_dev *edev; > +}; > + > +static const char * const tusb_attached_states[] = { > + [TUSB320_ATTACHED_STATE_NONE] = "not attached", > + [TUSB320_ATTACHED_STATE_DFP] = "downstream facing port", > + [TUSB320_ATTACHED_STATE_UFP] = "upstream facing port", > + [TUSB320_ATTACHED_STATE_ACC] = "accessory", > +}; > + > +static const unsigned int tusb320_extcon_cable[] = { > + EXTCON_USB, > + EXTCON_USB_HOST, > + EXTCON_NONE, > +}; > + > +static int tusb320_check_signature(struct tusb320_priv *priv) > +{ > + static const char sig[] = { '\0', 'T', 'U', 'S', 'B', '3', '2', '0' }; > + unsigned val; > + int i, ret; > + > + for (i = 0; i < sizeof(sig); i++) { > + ret = regmap_read(priv->regmap, sizeof(sig) - 1 - i, &val); > + if (ret < 0) > + return ret; > + if (val != sig[i]) { > + dev_err(priv->dev, "signature mismatch!\n"); > + return -ENODEV; > + } > + } > + > + return 0; > +} > + > +static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) > +{ > + struct tusb320_priv *priv = dev_id; > + int state, polarity; > + unsigned reg; > + > + if (regmap_read(priv->regmap, TUSB320_REG9, ®)) { > + dev_err(priv->dev, "error during i2c read!\n"); > + return IRQ_NONE; > + } > + > + if (!(reg & TUSB320_REG9_INTERRUPT_STATUS)) > + return IRQ_NONE; > + > + st
Re: [PATCH] tracing: Check return value of __create_val_fields() before using its result
On Tue, 13 Oct 2020 15:48:52 -0400 Steven Rostedt wrote: > From: "Steven Rostedt (VMware)" > > After having a typo for writing a histogram trigger. > > Wrote: > echo 'hist:key=pid:ts=common_timestamp.usec' > > events/sched/sched_waking/trigger > > Instead of: > echo 'hist:key=pid:ts=common_timestamp.usecs' > > events/sched/sched_waking/trigger > > and the following crash happened: > > BUG: kernel NULL pointer dereference, address: 0008 > #PF: supervisor read access in kernel mode > #PF: error_code(0x) - not-present page > PGD 0 P4D 0 > Oops: [#1] PREEMPT SMP PTI > CPU: 4 PID: 1641 Comm: sh Not tainted 5.9.0-rc5-test+ #549 > Hardware name: Hewlett-Packard HP Compaq Pro 6300 SFF/339A, BIOS K01 v03.03 > 07/14/2016 > RIP: 0010:event_hist_trigger_func+0x70b/0x1ee0 > Code: 24 08 89 d5 49 89 cc e9 8c 00 00 00 4c 89 f2 41 b9 00 10 00 00 4c 89 > e1 44 89 ee 4c 89 ff e8 dc d3 ff ff 45 89 ea 4b 8b 14 d7 42 08 04 74 17 > 41 8b 8f c0 00 00 00 8d 71 01 41 89 b7 c0 00 00 > RSP: 0018:959213d53db0 EFLAGS: 00010202 > RAX: ffea RBX: RCX: 00084c04 > RDX: RSI: df7326aefebd174c RDI: 00031080 > RBP: 0002 R08: 0001 R09: 0001 > R10: 0001 R11: 0046 R12: 959211dcf690 > R13: 0001 R14: 95925a36e370 R15: 959251c89800 > FS: 7fb9ea934740() GS:95925ab0() knlGS: > CS: 0010 DS: ES: CR0: 80050033 > CR2: 0008 CR3: c976c005 CR4: 001706e0 > Call Trace: > ? trigger_process_regex+0x78/0x110 > trigger_process_regex+0xc5/0x110 > event_trigger_write+0x71/0xd0 > vfs_write+0xca/0x210 > ksys_write+0x70/0xf0 > do_syscall_64+0x33/0x40 > entry_SYSCALL_64_after_hwframe+0x44/0xa9 > RIP: 0033:0x7fb9eaa29487 > Code: 64 89 02 48 c7 c0 ff ff ff ff eb bb 0f 1f 80 00 00 00 00 f3 0f 1e fa > 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff > 77 51 c3 48 83 ec 28 48 89 54 24 18 48 89 74 24 > > This was caused by accessing the hlist_data fields after the call to > __create_val_fields() without checking if the creation succeed. > This looks good to me. Reviewed-by: Masami Hiramatsu Thank you, > Fixes: 63a1e5de3006 ("tracing: Save normal string variables") > Signed-off-by: Steven Rostedt (VMware) > --- > kernel/trace/trace_events_hist.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/kernel/trace/trace_events_hist.c > b/kernel/trace/trace_events_hist.c > index c74a7d157306..96c3f86b81c5 100644 > --- a/kernel/trace/trace_events_hist.c > +++ b/kernel/trace/trace_events_hist.c > @@ -3687,7 +3687,7 @@ static int create_var_field(struct hist_trigger_data > *hist_data, > > ret = __create_val_field(hist_data, val_idx, file, var_name, expr_str, > flags); > > - if (hist_data->fields[val_idx]->flags & HIST_FIELD_FL_STRING) > + if (!ret && hist_data->fields[val_idx]->flags & HIST_FIELD_FL_STRING) > hist_data->fields[val_idx]->var_str_idx = > hist_data->n_var_str++; > > return ret; > -- > 2.25.4 > -- Masami Hiramatsu
Re: [PATCH v3 04/15] phy: tegra: xusb: tegra210: Do not reset UPHY PLL
Asserting reset to a PLL when it's managed by hardware power sequencer would break sequencer's state machine. Putting PLL in reset doesn't save some extra power. Thanks for review. JC On 9/28/20 9:06 PM, Thierry Reding wrote: > On Wed, Sep 09, 2020 at 04:10:30PM +0800, JC Kuo wrote: >> Once UPHY PLL hardware power sequencer is enabled, do not assert >> reset to PEX/SATA PLLs, otherwise UPHY PLL operation will be broken. >> This commit removes reset_control_assert(pcie->rst) and >> reset_control_assert(sata->rst) from PEX/SATA UPHY disable procedure. >> >> Signed-off-by: JC Kuo >> --- >> v3: >>new, was a part of "phy: tegra: xusb: Rearrange UPHY init on Tegra210" >> >> drivers/phy/tegra/xusb-tegra210.c | 2 -- >> 1 file changed, 2 deletions(-) >> >> diff --git a/drivers/phy/tegra/xusb-tegra210.c >> b/drivers/phy/tegra/xusb-tegra210.c >> index f06e7bc7a51b..ef4bbcbed60b 100644 >> --- a/drivers/phy/tegra/xusb-tegra210.c >> +++ b/drivers/phy/tegra/xusb-tegra210.c >> @@ -504,7 +504,6 @@ static void tegra210_pex_uphy_disable(struct >> tegra_xusb_padctl *padctl) >> if (--pcie->enable > 0) >> goto unlock; >> >> -reset_control_assert(pcie->rst); >> clk_disable_unprepare(pcie->pll); >> >> unlock: >> @@ -746,7 +745,6 @@ static void tegra210_sata_uphy_disable(struct >> tegra_xusb_padctl *padctl) >> if (--sata->enable > 0) >> goto unlock; >> >> -reset_control_assert(sata->rst); >> clk_disable_unprepare(sata->pll); >> >> unlock: > > Does this mean that we can no longer reset these PLLs anymore? Is that > safe? Would we ever need to reset them for recovery or similar? For > power saving, is disabling the clock enough, or could we save some extra > power by putting the PLLs into reset? > > Thierry >
Re: [PATCH] powerpc/features: Remove CPU_FTR_NODSISRALIGN
On 10/13/20 3:45 PM, Michael Ellerman wrote: Christophe Leroy writes: Le 13/10/2020 à 09:23, Aneesh Kumar K.V a écrit : Christophe Leroy writes: CPU_FTR_NODSISRALIGN has not been used since commit 31bfdb036f12 ("powerpc: Use instruction emulation infrastructure to handle alignment faults") Remove it. Signed-off-by: Christophe Leroy --- arch/powerpc/include/asm/cputable.h | 22 ++ arch/powerpc/kernel/dt_cpu_ftrs.c | 8 arch/powerpc/kernel/prom.c | 2 +- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c index 1098863e17ee..c598961d9f15 100644 --- a/arch/powerpc/kernel/dt_cpu_ftrs.c +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c @@ -273,13 +273,6 @@ static int __init feat_enable_idle_nap(struct dt_cpu_feature *f) return 1; } -static int __init feat_enable_align_dsisr(struct dt_cpu_feature *f) -{ - cur_cpu_spec->cpu_features &= ~CPU_FTR_NODSISRALIGN; - - return 1; -} - static int __init feat_enable_idle_stop(struct dt_cpu_feature *f) { u64 lpcr; @@ -641,7 +634,6 @@ static struct dt_cpu_feature_match __initdata {"tm-suspend-hypervisor-assist", feat_enable, CPU_FTR_P9_TM_HV_ASSIST}, {"tm-suspend-xer-so-bug", feat_enable, CPU_FTR_P9_TM_XER_SO_BUG}, {"idle-nap", feat_enable_idle_nap, 0}, - {"alignment-interrupt-dsisr", feat_enable_align_dsisr, 0}, Rather than removing it entirely, I'd rather we left a comment, so that it's obvious that we are ignoring that feature on purpose, not because we forget about it. eg: diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c index f204ad79b6b5..45cb7e59bd13 100644 --- a/arch/powerpc/kernel/dt_cpu_ftrs.c +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c @@ -640,7 +640,7 @@ static struct dt_cpu_feature_match __initdata {"tm-suspend-hypervisor-assist", feat_enable, CPU_FTR_P9_TM_HV_ASSIST}, {"tm-suspend-xer-so-bug", feat_enable, CPU_FTR_P9_TM_XER_SO_BUG}, {"idle-nap", feat_enable_idle_nap, 0}, - {"alignment-interrupt-dsisr", feat_enable_align_dsisr, 0}, + // "alignment-interrupt-dsisr" ignored {"idle-stop", feat_enable_idle_stop, 0}, {"machine-check-power8", feat_enable_mce_power8, 0}, {"performance-monitor-power8", feat_enable_pmu_power8, 0}, why not do it as static int __init feat_enable_align_dsisr(struct dt_cpu_feature *f) { /* This feature should not be enabled */ #ifdef DEBUG WARN(1); #endif return 1; } -aneesh
[PATCH v1 5/6] i2c: iproc: handle master read request
On Sun, 11 Oct 2020 23:52:53 +0530, Rayagonda Kokatanur wrote: > --- a/drivers/i2c/busses/i2c-bcm-iproc.c > +++ b/drivers/i2c/busses/i2c-bcm-iproc.c > > - } else if (status & BIT(IS_S_RD_EVENT_SHIFT)) { > - /* Start of SMBUS for Master Read */ > + I2C_SLAVE_WRITE_REQUESTED, &rx_data); > + iproc_i2c->rx_start_rcvd = true; > + iproc_i2c->slave_read_complete = false; > + } else if (rx_status == I2C_SLAVE_RX_DATA && > +iproc_i2c->rx_start_rcvd) { > + /* Middle of SMBUS Master write */ > i2c_slave_event(iproc_i2c->slave, > - I2C_SLAVE_READ_REQUESTED, &value); > - iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, value); > + I2C_SLAVE_WRITE_RECEIVED, &rx_data); > + } else if (rx_status == I2C_SLAVE_RX_END && > +iproc_i2c->rx_start_rcvd) { > + /* End of SMBUS Master write */ > + if (iproc_i2c->slave_rx_only) > + i2c_slave_event(iproc_i2c->slave, > + I2C_SLAVE_WRITE_RECEIVED, > + &rx_data); > + > + i2c_slave_event(iproc_i2c->slave, I2C_SLAVE_STOP, > + &rx_data); > + } else if (rx_status == I2C_SLAVE_RX_FIFO_EMPTY) { > + iproc_i2c->rx_start_rcvd = false; > + iproc_i2c->slave_read_complete = true; > + break; > + } > > - val = BIT(S_CMD_START_BUSY_SHIFT); > - iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val); > + rx_bytes++; rx_bytes should be incremented only along with I2C_SLAVE_WRITE_RECEIVED event? > > +static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c, > + u32 status) > +{ > + u32 val; > + u8 value; > + > + /* > + * Slave events in case of master-write, master-write-read and, > + * master-read > + * > + * Master-write : only IS_S_RX_EVENT_SHIFT event > + * Master-write-read: both IS_S_RX_EVENT_SHIFT and IS_S_RD_EVENT_SHIFT > + *events > + * Master-read : both IS_S_RX_EVENT_SHIFT and IS_S_RD_EVENT_SHIFT > + *events or only IS_S_RD_EVENT_SHIFT > + */ > + if (status & BIT(IS_S_RX_EVENT_SHIFT) || > + status & BIT(IS_S_RD_EVENT_SHIFT)) { > + /* disable slave interrupts */ > + val = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET); > + val &= ~iproc_i2c->slave_int_mask; > + iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val); > + > + if (status & BIT(IS_S_RD_EVENT_SHIFT)) > + /* Master-write-read request */ > + iproc_i2c->slave_rx_only = false; > + else > + /* Master-write request only */ > + iproc_i2c->slave_rx_only = true; > + > + /* schedule tasklet to read data later */ > + tasklet_schedule(&iproc_i2c->slave_rx_tasklet); > + > + /* clear only IS_S_RX_EVENT_SHIFT interrupt */ > + iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, > + BIT(IS_S_RX_EVENT_SHIFT)); > Both tasklet and isr are writing to status (IS_OFFSET) reg. The tasklet seems to be batching up rx fifo reads because of time-sensitive Master-write-read transaction? Linux I2C framework is byte interface anyway. Can the need to batch reads be avoided by setting slave rx threshold for interrupt (S_FIFO_RX_THLD) to 1-byte? Also, wouldn't tasklets be susceptible to other interrupts? If fifo reads have to be batched up, can it be changed to threaded irq?
[PATCH v7 4/4] mmc: mediatek: Add subsys clock control for MT8192 msdc
MT8192 msdc is an independent sub system, we need control more bus clocks for it. Add support for the additional subsys clocks to allow it to be configured appropriately. Signed-off-by: Wenbin Mei Reviewed-by: Nicolas Boichat --- drivers/mmc/host/mtk-sd.c | 74 +-- 1 file changed, 56 insertions(+), 18 deletions(-) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index a704745e5882..c7df7510f120 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -35,6 +35,7 @@ #include "cqhci.h" #define MAX_BD_NUM 1024 +#define MSDC_NR_CLOCKS 3 /*--*/ /* Common Definition*/ @@ -425,6 +426,8 @@ struct msdc_host { struct clk *h_clk; /* msdc h_clk */ struct clk *bus_clk;/* bus clock which used to access register */ struct clk *src_clk_cg; /* msdc source clock control gate */ + struct clk *sys_clk_cg; /* msdc subsys clock control gate */ + struct clk_bulk_data bulk_clks[MSDC_NR_CLOCKS]; u32 mclk; /* mmc subsystem clock frequency */ u32 src_clk_freq; /* source clock frequency */ unsigned char timing; @@ -784,6 +787,7 @@ static void msdc_set_busy_timeout(struct msdc_host *host, u64 ns, u64 clks) static void msdc_gate_clock(struct msdc_host *host) { + clk_bulk_disable_unprepare(MSDC_NR_CLOCKS, host->bulk_clks); clk_disable_unprepare(host->src_clk_cg); clk_disable_unprepare(host->src_clk); clk_disable_unprepare(host->bus_clk); @@ -792,10 +796,18 @@ static void msdc_gate_clock(struct msdc_host *host) static void msdc_ungate_clock(struct msdc_host *host) { + int ret; + clk_prepare_enable(host->h_clk); clk_prepare_enable(host->bus_clk); clk_prepare_enable(host->src_clk); clk_prepare_enable(host->src_clk_cg); + ret = clk_bulk_prepare_enable(MSDC_NR_CLOCKS, host->bulk_clks); + if (ret) { + dev_err(host->dev, "Cannot enable pclk/axi/ahb clock gates\n"); + return; + } + while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB)) cpu_relax(); } @@ -2366,6 +2378,48 @@ static void msdc_of_property_parse(struct platform_device *pdev, host->cqhci = false; } +static int msdc_of_clock_parse(struct platform_device *pdev, + struct msdc_host *host) +{ + int ret; + + host->src_clk = devm_clk_get(&pdev->dev, "source"); + if (IS_ERR(host->src_clk)) + return PTR_ERR(host->src_clk); + + host->h_clk = devm_clk_get(&pdev->dev, "hclk"); + if (IS_ERR(host->h_clk)) + return PTR_ERR(host->h_clk); + + host->bus_clk = devm_clk_get_optional(&pdev->dev, "bus_clk"); + if (IS_ERR(host->bus_clk)) + host->bus_clk = NULL; + + /*source clock control gate is optional clock*/ + host->src_clk_cg = devm_clk_get_optional(&pdev->dev, "source_cg"); + if (IS_ERR(host->src_clk_cg)) + host->src_clk_cg = NULL; + + host->sys_clk_cg = devm_clk_get_optional(&pdev->dev, "sys_cg"); + if (IS_ERR(host->sys_clk_cg)) + host->sys_clk_cg = NULL; + + /* If present, always enable for this clock gate */ + clk_prepare_enable(host->sys_clk_cg); + + host->bulk_clks[0].id = "pclk_cg"; + host->bulk_clks[1].id = "axi_cg"; + host->bulk_clks[2].id = "ahb_cg"; + ret = devm_clk_bulk_get_optional(&pdev->dev, MSDC_NR_CLOCKS, +host->bulk_clks); + if (ret) { + dev_err(&pdev->dev, "Cannot get pclk/axi/ahb clock gates\n"); + return ret; + } + + return 0; +} + static int msdc_drv_probe(struct platform_device *pdev) { struct mmc_host *mmc; @@ -2405,25 +2459,9 @@ static int msdc_drv_probe(struct platform_device *pdev) if (ret) goto host_free; - host->src_clk = devm_clk_get(&pdev->dev, "source"); - if (IS_ERR(host->src_clk)) { - ret = PTR_ERR(host->src_clk); - goto host_free; - } - - host->h_clk = devm_clk_get(&pdev->dev, "hclk"); - if (IS_ERR(host->h_clk)) { - ret = PTR_ERR(host->h_clk); + ret = msdc_of_clock_parse(pdev, host); + if (ret) goto host_free; - } - - host->bus_clk = devm_clk_get(&pdev->dev, "bus_clk"); - if (IS_ERR(host->bus_clk)) - host->bus_clk = NULL; - /*source clock control gate is optional clock*/ - host->src_clk_cg = devm_clk_get(&pdev->dev, "source_cg"); - if (IS_ERR(host->src_clk_cg)) - host->src_clk_cg = NULL; host->reset = devm_reset_control_get_optional_exclusive(&pdev->dev,
[PATCH v7 3/4] arm64: dts: mt8192: add mmc device node
This commit adds mmc device node for mt8192 Signed-off-by: Wenbin Mei --- arch/arm64/boot/dts/mediatek/mt8192-evb.dts | 89 + arch/arm64/boot/dts/mediatek/mt8192.dtsi| 34 2 files changed, 123 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8192-evb.dts b/arch/arm64/boot/dts/mediatek/mt8192-evb.dts index 0205837fa698..a4279fa87c2b 100644 --- a/arch/arm64/boot/dts/mediatek/mt8192-evb.dts +++ b/arch/arm64/boot/dts/mediatek/mt8192-evb.dts @@ -5,6 +5,7 @@ */ /dts-v1/; #include "mt8192.dtsi" +#include "mt6359.dtsi" / { model = "MediaTek MT8192 evaluation board"; @@ -27,3 +28,91 @@ &uart0 { status = "okay"; }; + +&mmc0 { + status = "okay"; + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + bus-width = <8>; + max-frequency = <2>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + supports-cqe; + cap-mmc-hw-reset; + no-sdio; + no-sd; + hs400-ds-delay = <0x12814>; + vmmc-supply = <&mt6359_vemc_1_ldo_reg>; + vqmmc-supply = <&mt6359_vufs_ldo_reg>; + assigned-clocks = <&topckgen CLK_TOP_MSDC50_0_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_MSDCPLL>; + non-removable; +}; + +&pio { + mmc0_pins_default: mmc0default { + pins_cmd_dat { + pinmux = , +, +, +, +, +, +, +, +; + input-enable; + drive-strenth = <3>; + mediatek,pull-up-adv = <1>; + }; + + pins_clk { + pinmux = ; + drive-strenth = <3>; + mediatek,pull-down-adv = <2>; + }; + + pins_rst { + pinmux = ; + drive-strenth = <3>; + mediatek,pull-up-adv = <1>; + }; + }; + + mmc0_pins_uhs: mmc0@0{ + pins_cmd_dat { + pinmux = , +, +, +, +, +, +, +, +; + input-enable; + drive-strenth = <4>; + mediatek,pull-up-adv = <1>; + }; + + pins_clk { + pinmux = ; + drive-strenth = <4>; + mediatek,pull-down-adv = <2>; + }; + + pins_ds { + pinmux = ; + drive-strenth = <4>; + mediatek,pull-down-adv = <2>; + }; + + pins_rst { + pinmux = ; + drive-strenth = <3>; + mediatek,pull-up-adv = <1>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/mediatek/mt8192.dtsi b/arch/arm64/boot/dts/mediatek/mt8192.dtsi index faea0d97c2a9..de3d10c0eeef 100644 --- a/arch/arm64/boot/dts/mediatek/mt8192.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8192.dtsi @@ -760,6 +760,40 @@ #clock-cells = <1>; }; + mmc0: mmc@11f6 { + compatible = "mediatek,mt8192-mmc", "mediatek,mt8183-mmc"; + reg = <0 0x11f6 0 0x1000>, + <0 0x11f5 0 0x1000>; + interrupts = ; + clocks = <&topckgen CLK_TOP_MSDC50_0_SEL>, +<&msdc_top CLK_MSDC_TOP_H_MST_0P>, +<&msdc_top CLK_MSDC_TOP_SRC_0P>, +<&msdc_top CLK_MSDC_TOP_P_CFG>, +<&msdc_top CLK_MSDC_TOP_P_MSDC0>, +<&msdc_top CLK_MSDC_TOP_AXI>, +<&msdc_top CLK_MSDC_TOP_AHB2AXI_BRG_AXI>; + clock-names = "source", "hclk", "source_cg", "sys_cg", + "pclk_cg", "axi_cg", "ahb_cg"; + status = "disabled"; + }; + + mmc1: mmc@11f7 { + compatible = "mediatek,mt8192-mmc", "mediatek,mt8183-mmc"; + reg = <0 0x11f7 0 0x1000>, + <0 0x11c7 0 0x1000>; + interrupts = ; + clocks = <&topckgen CLK_TOP_MSDC30_1_SEL>, +
[PATCH v7 1/4] dt-bindings: mmc: Convert mtk-sd to json-schema
Convert the mtk-sd binding to DT schema format using json-schema. Signed-off-by: Wenbin Mei Reviewed-by: Rob Herring --- .../devicetree/bindings/mmc/mtk-sd.txt| 75 .../devicetree/bindings/mmc/mtk-sd.yaml | 165 ++ 2 files changed, 165 insertions(+), 75 deletions(-) delete mode 100644 Documentation/devicetree/bindings/mmc/mtk-sd.txt create mode 100644 Documentation/devicetree/bindings/mmc/mtk-sd.yaml diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.txt b/Documentation/devicetree/bindings/mmc/mtk-sd.txt deleted file mode 100644 index 26a8f320a156.. --- a/Documentation/devicetree/bindings/mmc/mtk-sd.txt +++ /dev/null @@ -1,75 +0,0 @@ -* MTK MMC controller - -The MTK MSDC can act as a MMC controller -to support MMC, SD, and SDIO types of memory cards. - -This file documents differences between the core properties in mmc.txt -and the properties used by the msdc driver. - -Required properties: -- compatible: value should be either of the following. - "mediatek,mt8135-mmc": for mmc host ip compatible with mt8135 - "mediatek,mt8173-mmc": for mmc host ip compatible with mt8173 - "mediatek,mt8183-mmc": for mmc host ip compatible with mt8183 - "mediatek,mt8516-mmc": for mmc host ip compatible with mt8516 - "mediatek,mt6779-mmc": for mmc host ip compatible with mt6779 - "mediatek,mt2701-mmc": for mmc host ip compatible with mt2701 - "mediatek,mt2712-mmc": for mmc host ip compatible with mt2712 - "mediatek,mt7622-mmc": for MT7622 SoC - "mediatek,mt7623-mmc", "mediatek,mt2701-mmc": for MT7623 SoC - "mediatek,mt7620-mmc", for MT7621 SoC (and others) - -- reg: physical base address of the controller and length -- interrupts: Should contain MSDC interrupt number -- clocks: Should contain phandle for the clock feeding the MMC controller -- clock-names: Should contain the following: - "source" - source clock (required) - "hclk" - HCLK which used for host (required) - "source_cg" - independent source clock gate (required for MT2712) - "bus_clk" - bus clock used for internal register access (required for MT2712 MSDC0/3) -- pinctrl-names: should be "default", "state_uhs" -- pinctrl-0: should contain default/high speed pin ctrl -- pinctrl-1: should contain uhs mode pin ctrl -- vmmc-supply: power to the Core -- vqmmc-supply: power to the IO - -Optional properties: -- assigned-clocks: PLL of the source clock -- assigned-clock-parents: parent of source clock, used for HS400 mode to get 400Mhz source clock -- hs400-ds-delay: HS400 DS delay setting -- mediatek,hs200-cmd-int-delay: HS200 command internal delay setting. - This field has total 32 stages. - The value is an integer from 0 to 31. -- mediatek,hs400-cmd-int-delay: HS400 command internal delay setting - This field has total 32 stages. - The value is an integer from 0 to 31. -- mediatek,hs400-cmd-resp-sel-rising: HS400 command response sample selection - If present,HS400 command responses are sampled on rising edges. - If not present,HS400 command responses are sampled on falling edges. -- mediatek,latch-ck: Some SoCs do not support enhance_rx, need set correct latch-ck to avoid data crc -error caused by stop clock(fifo full) -Valid range = [0:0x7]. if not present, default value is 0. -applied to compatible "mediatek,mt2701-mmc". -- resets: Phandle and reset specifier pair to softreset line of MSDC IP. -- reset-names: Should be "hrst". - -Examples: -mmc0: mmc@1123 { - compatible = "mediatek,mt8173-mmc", "mediatek,mt8135-mmc"; - reg = <0 0x1123 0 0x108>; - interrupts = ; - vmmc-supply = <&mt6397_vemc_3v3_reg>; - vqmmc-supply = <&mt6397_vio18_reg>; - clocks = <&pericfg CLK_PERI_MSDC30_0>, -<&topckgen CLK_TOP_MSDC50_0_H_SEL>; - clock-names = "source", "hclk"; - pinctrl-names = "default", "state_uhs"; - pinctrl-0 = <&mmc0_pins_default>; - pinctrl-1 = <&mmc0_pins_uhs>; - assigned-clocks = <&topckgen CLK_TOP_MSDC50_0_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_MSDCPLL_D2>; - hs400-ds-delay = <0x14015>; - mediatek,hs200-cmd-int-delay = <26>; - mediatek,hs400-cmd-int-delay = <14>; - mediatek,hs400-cmd-resp-sel-rising; -}; diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml new file mode 100644 index ..79905df75f1d --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml @@ -0,0 +1,165 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/mtk-sd.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MTK MSDC
[PATCH v7 2/4] mmc: dt-bindings: add support for MT8192 SoC
MT8192 mmc host ip is compatible with MT8183. Add support for this. Signed-off-by: Wenbin Mei --- Documentation/devicetree/bindings/mmc/mtk-sd.yaml | 15 +-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml index 79905df75f1d..030e3fdce492 100644 --- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml @@ -29,26 +29,37 @@ properties: - items: - const: mediatek,mt7623-mmc - const: mediatek,mt2701-mmc + - items: +- const: mediatek,mt8192-mmc +- const: mediatek,mt8183-mmc clocks: description: Should contain phandle for the clock feeding the MMC controller. minItems: 2 -maxItems: 4 +maxItems: 8 items: - description: source clock (required). - description: HCLK which used for host (required). - description: independent source clock gate (required for MT2712). - description: bus clock used for internal register access (required for MT2712 MSDC0/3). + - description: msdc subsys clock gate (required for MT8192). + - description: peripheral bus clock gate (required for MT8192). + - description: AXI bus clock gate (required for MT8192). + - description: AHB bus clock gate (required for MT8192). clock-names: minItems: 2 -maxItems: 4 +maxItems: 8 items: - const: source - const: hclk - const: source_cg - const: bus_clk + - const: sys_cg + - const: pclk_cg + - const: axi_cg + - const: ahb_cg pinctrl-names: items: -- 2.18.0
[PATCH v7 0/4] Add mmc support for MT8192 SoC
Change in v7: 1)add "unevaluatedProperties" in mtk-sd.yaml 2)add Reviewed-by tag Change in v6: 1)use devm_clk_get function for required clocks Change in v5: 1)remove Reviewed-by tag 2)use devm_clk_bulk_get_optional instead of devm_clk_get_optional for bulk clks Change in v4: 1)drop "vmmc" and "vqmmc" desciption in mtk-sd.yaml 2)add vmmq/vqmmc supplies and the pinctrls to required properties 3)change dbg level and exit this function 4)use devm_clk_get_optional instead of devm_clk_get function 5)remove else branch for sys_clk_cg Change in v3: 1)change maintainers name in mtk-sd.yaml 2)change "compatible" properties to enum type and sort it 3)drop these properties: "reg" and "interrupts" 4)add "maxItems" constraints on these properties: "vmmc-supply", "vqmmc-supply", "assigned-clocks", "assigned-clock-parents" 5)add "minimum" and "maximum" constraints on these properties: "mediatek,hs400-cmd-int-delay", "mediatek,latch-ck", "hs400-ds-delay", "mediatek,hs200-cmd-int-delay" Change in v2: Convert mtk-sd to json-schema Wenbin Mei (4): dt-bindings: mmc: Convert mtk-sd to json-schema mmc: dt-bindings: add support for MT8192 SoC arm64: dts: mt8192: add mmc device node mmc: mediatek: Add subsys clock control for MT8192 msdc --- This patch depends on [v4,1/3] arm64: dts: Add Mediatek SoC MT8192 and evaluation board dts and Makefile [v3,1/9] dt-bindings: ARM: Mediatek: Document bindings for MT8192 BSP [v3,6/9] clk: mediatek: Add dt-bindings for MT8192 clocks [v3,9/9] clk: mediatek: Add MT8192 clock support [v3,1/3] dt-bindings: pinctrl: mt8192: add pinctrl file [v3,2/3] dt-bindings: pinctrl: mt8192: add binding document [v3,3/3] pinctrl: add pinctrl driver on mt8192 [v2,1/4] soc: mediatek: pwrap: use BIT() macro [v2,2/4] soc: mediatek: pwrap: add arbiter capability [v2,3/4] dt-bindings: mediatek: add compatible for MT6873/8192 pwrap [v2,4/4] soc: mediatek: pwrap: add pwrap driver for MT6873/8192 SoCs [2/8] dt-bindings: mfd: Add compatible for the MediaTek MT6359 PMIC [3/8] dt-bindings: regulator: Add document for MT6359 regulator [4/8] mfd: Add support for the MediaTek MT6359 PMIC [5/8] regulator: mt6359: Add support for MT6359 regulator [7/8] regulator: mt6359: Add support for MT6359P regulator [8/8] arm64: dts: mt6359: add PMIC MT6359 related nodes Please also accept this patch together with [1][2][3][4][5] to avoid build and dt binding check error. [1] https://patchwork.kernel.org/project/linux-mediatek/list/?series=332621 [2] https://patchwork.kernel.org/project/linux-mediatek/list/?series=342593 [3] https://patchwork.kernel.org/project/linux-mediatek/list/?series=330017 [4] https://patchwork.kernel.org/project/linux-mediatek/list/?series=322937 [5] https://patchwork.kernel.org/project/linux-mediatek/list/?series=323171 --- .../devicetree/bindings/mmc/mtk-sd.txt| 75 .../devicetree/bindings/mmc/mtk-sd.yaml | 176 ++ arch/arm64/boot/dts/mediatek/mt8192-evb.dts | 89 + arch/arm64/boot/dts/mediatek/mt8192.dtsi | 34 drivers/mmc/host/mtk-sd.c | 74 ++-- 5 files changed, 355 insertions(+), 93 deletions(-) delete mode 100644 Documentation/devicetree/bindings/mmc/mtk-sd.txt create mode 100644 Documentation/devicetree/bindings/mmc/mtk-sd.yaml -- 2.18.0
Re: [PATCH 1/5] clk: ingenic: Use to_clk_info() macro for all clocks
Quoting Paul Cercueil (2020-09-02 18:50:44) > The to_clk_info() previously had a BUG_ON() to check that it was only > called for PLL clocks. Yet, all the other clocks were doing the exact > same thing the macro does, in-line. > > Move the to_clk_info() macro to the top of the file, remove the > hardcoded BUG_ON(), and use it everywhere it makes sense. > > Signed-off-by: Paul Cercueil > --- Applied to clk-next
Re: [PATCH 2/5] clk: ingenic: Use readl_poll_timeout instead of custom loop
Quoting Paul Cercueil (2020-09-02 18:50:45) > Use the readl_poll_timeout() function instead of rolling our own > busy-wait loops. This makes the code simpler. > > Signed-off-by: Paul Cercueil > --- Applied to clk-next
Re: [PATCH 4/5] clk: ingenic: Don't tag custom clocks with CLK_SET_RATE_PARENT
Quoting Paul Cercueil (2020-09-02 18:50:47) > The custom clocks have custom functions to round, get or set their rate. > Therefore, we can't assume that they need the CLK_SET_RATE_PARENT flag. > > Signed-off-by: Paul Cercueil > --- Applied to clk-next
Re: [PATCH 3/5] clk: ingenic: Don't use CLK_SET_RATE_GATE for PLL
Quoting Paul Cercueil (2020-09-02 18:50:46) > CLK_SET_RATE_GATE means that the clock must be gated when being > reclocked. This is not the case for the PLLs in Ingenic SoCs. > > Signed-off-by: Paul Cercueil > --- Applied to clk-next
Re: [PATCH 5/5] clk: ingenic: Respect CLK_SET_RATE_PARENT in .round_rate
Quoting Paul Cercueil (2020-09-02 18:50:48) > Clocks that don't have a divider are in our case all marked with the > CLK_SET_RATE_PARENT flag. In this case, the .round_rate implementation > should modify the value pointed to by parent_rate, in order to propagate > the rate change to the parent, as explained in the documentation of > clk_set_rate(). > > Signed-off-by: Paul Cercueil > --- Applied to clk-next
Re: [PATCH] clk: bcm2835: add missing release if devm_clk_hw_register fails
Quoting Navid Emamdoost (2020-08-09 16:11:58) > In the implementation of bcm2835_register_pll(), the allocated pll is > leaked if devm_clk_hw_register() fails to register hw. Release pll if > devm_clk_hw_register() fails. > > Signed-off-by: Navid Emamdoost > --- Applied to clk-next
Re: [PATCH v2 3/3] clk: at91: clk-sam9x60-pll: remove unused variable
Quoting Claudiu Beznea (2020-08-24 23:59:11) > Fix variable set but not used compilation warning. > > Fixes: 43b1bb4a9b3e ("clk: at91: clk-sam9x60-pll: re-factor to support plls > with multiple outputs") > Reported-by: kernel test robot > Signed-off-by: Claudiu Beznea > --- Applied to clk-next
Re: [PATCH v2 1/3] clk: at91: remove the checking of parent_name
Quoting Claudiu Beznea (2020-08-24 23:59:09) > There is no need to check parent_name variable while assigning it to > init.parent_names. parent_name variable is already checked at > the beginning of at91_clk_register_peripheral() function. > > Fixes: 6114067e437eb ("clk: at91: add PMC peripheral clocks") > Signed-off-by: Claudiu Beznea > Reviewed-by: Alexandre Belloni > --- Applied to clk-next
Re: [PATCH v2 2/3] clk: at91: clk-main: update key before writing AT91_CKGR_MOR
Quoting Claudiu Beznea (2020-08-24 23:59:10) > SAMA5D2 datasheet specifies on chapter 33.22.8 (PMC Clock Generator > Main Oscillator Register) that writing any value other than > 0x37 on KEY field aborts the write operation. Use the key when > selecting main clock parent. > > Fixes: 27cb1c2083373 ("clk: at91: rework main clk implementation") > Signed-off-by: Claudiu Beznea > Reviewed-by: Alexandre Belloni > --- Applied to clk-next
Re: [PATCH] clk: clk-prima2: fix return value check in prima2_clk_init()
Quoting Xu Wang (2020-09-20 20:45:22) > In case of error, the function clk_register() returns ERR_PTR() > and never returns NULL. The NULL test in the return value check > should be replaced with IS_ERR(). > > Signed-off-by: Xu Wang > --- Applied to clk-next
Re: [PATCH] clk: mmp2: Fix the display clock divider base
Quoting Lubomir Rintel (2020-09-25 16:39:14) > The LCD clock dividers are apparently based on one. No datasheet, > determined empirically, but seems to be confirmed by line 19 of lcd.fth in > OLPC laptop's Open Firmware [1]: > >h# 0700 value pmua-disp-clk-sel \ PLL1 / 7 -> 113.86 MHz > > [1] > https://raw.githubusercontent.com/quozl/openfirmware/65a08a73b2cac/cpu/arm/olpc/lcd.fth > > Signed-off-by: Lubomir Rintel > --- Applied to clk-next
Re: [PATCH 1/1] clk: aspeed: modify some default clks are critical
Quoting Ryan Chen (2020-09-28 00:01:08) > In ASPEED SoC LCLK is LPC clock for all SuperIO device, UART1/UART2 are > default for Host SuperIO UART device, eSPI clk for Host eSPI bus access > eSPI slave channel, those clks can't be disable should keep default, > otherwise will affect Host side access SuperIO and SPI slave device. > > Signed-off-by: Ryan Chen > --- Is there resolution on this thread?
Re: [PATCH 1/2] clk: qoriq: modify MAX_PLL_DIV to 32
Quoting Qiang Zhao (2020-09-15 20:03:10) > From: Zhao Qiang > > On LS2088A, Watchdog need clk divided by 32, > so modify MAX_PLL_DIV to 32 > > Signed-off-by: Zhao Qiang > --- Applied to clk-next
Re: [PATCH] clk: baikal-t1: Mark Ethernet PLL as critical
Quoting Serge Semin (2020-09-20 04:03:35) > We've discovered that disabling the so called Ethernet PLL causes reset of > the devices consuming its outgoing clock. The resets happen automatically > even if each underlying clock gate is turned off. Due to that we can't > disable the Ethernet PLL until the kernel is prepared for the corresponding > resets. So for now just mark the PLL clock provider as critical. > > Signed-off-by: Serge Semin > Cc: Alexey Malahov > Cc: linux-m...@vger.kernel.org > --- Applied to clk-next
[PATCH stable-5.4] backport enospc issues during balance
Patch 1 is a preparatory patch to reduce conflicts. Patch 2 fixes balance failure due to ENOSPC in btrfs/156 on arm64 systems with pagesize=64k. Minor conflicts in fs/btrfs/block-group.c are resolved. Thanks. Josef Bacik (2): btrfs: don't pass system_chunk into can_overcommit btrfs: take overcommit into account in inc_block_group_ro fs/btrfs/block-group.c | 38 ++-- fs/btrfs/space-info.c | 50 +- fs/btrfs/space-info.h | 3 +++ 3 files changed, 49 insertions(+), 42 deletions(-) -- 2.18.4
Re: [PATCH 1/2] clk: axi-clkgen: Add support for fractional dividers
Quoting Alexandru Ardelean (2020-10-01 01:59:47) > From: Lars-Peter Clausen > > The axi-clkgen has (optional) fractional dividers on the output clock > divider and feedback clock divider path. Utilizing the fractional dividers > allows for a better resolution of the output clock, being able to > synthesize more frequencies. > > Rework the driver support to support the fractional register fields, both > for setting a new rate as well as reading back the current rate from the > hardware. > > For setting the rate if no perfect divider settings were found in > non-fractional mode try again in fractional mode and see if better settings > can be found. This appears to be the recommended mode of operation. > > Signed-off-by: Lars-Peter Clausen > Signed-off-by: Alexandru Ardelean > --- Applied to clk-next
Re: [PATCH 2/2] clk: axi-clkgen: Set power bits for fractional mode
Quoting Alexandru Ardelean (2020-10-01 01:59:48) > From: Lars-Peter Clausen > > Using the fractional dividers requires some additional power bits to be > set. > > The fractional power bits are not documented and the current heuristic > for setting them seems be insufficient for some cases. Just always set all > the fractional power bits when in fractional mode. > > Signed-off-by: Lars-Peter Clausen > Signed-off-by: Alexandru Ardelean > --- Applied to clk-next
[PATCH stable-5.4 1/2] btrfs: don't pass system_chunk into can_overcommit
From: Josef Bacik commit 9f246926b4d5db4c5e8c78e4897757de26c95be6 upstream We have the space_info, we can just check its flags to see if it's the system chunk space info. Reviewed-by: Nikolay Borisov Reviewed-by: Qu Wenruo Reviewed-by: Johannes Thumshirn Signed-off-by: Josef Bacik Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Anand Jain --- fs/btrfs/space-info.c | 42 +++--- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 6f484f0d347e..e19e538d05f9 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -162,8 +162,7 @@ static inline u64 calc_global_rsv_need_space(struct btrfs_block_rsv *global) static int can_overcommit(struct btrfs_fs_info *fs_info, struct btrfs_space_info *space_info, u64 bytes, - enum btrfs_reserve_flush_enum flush, - bool system_chunk) + enum btrfs_reserve_flush_enum flush) { u64 profile; u64 avail; @@ -174,7 +173,7 @@ static int can_overcommit(struct btrfs_fs_info *fs_info, if (space_info->flags & BTRFS_BLOCK_GROUP_DATA) return 0; - if (system_chunk) + if (space_info->flags & BTRFS_BLOCK_GROUP_SYSTEM) profile = btrfs_system_alloc_profile(fs_info); else profile = btrfs_metadata_alloc_profile(fs_info); @@ -228,8 +227,7 @@ void btrfs_try_granting_tickets(struct btrfs_fs_info *fs_info, /* Check and see if our ticket can be satisified now. */ if ((used + ticket->bytes <= space_info->total_bytes) || - can_overcommit(fs_info, space_info, ticket->bytes, flush, - false)) { + can_overcommit(fs_info, space_info, ticket->bytes, flush)) { btrfs_space_info_update_bytes_may_use(fs_info, space_info, ticket->bytes); @@ -634,8 +632,7 @@ static void flush_space(struct btrfs_fs_info *fs_info, static inline u64 btrfs_calc_reclaim_metadata_size(struct btrfs_fs_info *fs_info, -struct btrfs_space_info *space_info, -bool system_chunk) +struct btrfs_space_info *space_info) { struct reserve_ticket *ticket; u64 used; @@ -651,13 +648,12 @@ btrfs_calc_reclaim_metadata_size(struct btrfs_fs_info *fs_info, to_reclaim = min_t(u64, num_online_cpus() * SZ_1M, SZ_16M); if (can_overcommit(fs_info, space_info, to_reclaim, - BTRFS_RESERVE_FLUSH_ALL, system_chunk)) + BTRFS_RESERVE_FLUSH_ALL)) return 0; used = btrfs_space_info_used(space_info, true); - if (can_overcommit(fs_info, space_info, SZ_1M, - BTRFS_RESERVE_FLUSH_ALL, system_chunk)) + if (can_overcommit(fs_info, space_info, SZ_1M, BTRFS_RESERVE_FLUSH_ALL)) expected = div_factor_fine(space_info->total_bytes, 95); else expected = div_factor_fine(space_info->total_bytes, 90); @@ -673,7 +669,7 @@ btrfs_calc_reclaim_metadata_size(struct btrfs_fs_info *fs_info, static inline int need_do_async_reclaim(struct btrfs_fs_info *fs_info, struct btrfs_space_info *space_info, - u64 used, bool system_chunk) + u64 used) { u64 thresh = div_factor_fine(space_info->total_bytes, 98); @@ -681,8 +677,7 @@ static inline int need_do_async_reclaim(struct btrfs_fs_info *fs_info, if ((space_info->bytes_used + space_info->bytes_reserved) >= thresh) return 0; - if (!btrfs_calc_reclaim_metadata_size(fs_info, space_info, - system_chunk)) + if (!btrfs_calc_reclaim_metadata_size(fs_info, space_info)) return 0; return (used >= thresh && !btrfs_fs_closing(fs_info) && @@ -805,8 +800,7 @@ static void btrfs_async_reclaim_metadata_space(struct work_struct *work) space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); spin_lock(&space_info->lock); - to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info, space_info, - false); + to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info, space_info); if (!to_reclaim) { space_info->flush = 0; spin_unlock(&space_info->lock); @@ -825,8 +819,7 @@ static void btrfs_async_reclaim_metadata_space(struct work_struct *work) return; } to_reclaim = btrfs_calc_reclaim_metadata_
[PATCH stable-5.4 2/2] btrfs: take overcommit into account in inc_block_group_ro
From: Josef Bacik commit a30a3d2067536cbcce26c055e70cc3a6ae4fd45c upstream inc_block_group_ro does a calculation to see if we have enough room left over if we mark this block group as read only in order to see if it's ok to mark the block group as read only. The problem is this calculation _only_ works for data, where our used is always less than our total. For metadata we will overcommit, so this will almost always fail for metadata. Fix this by exporting btrfs_can_overcommit, and then see if we have enough space to remove the remaining free space in the block group we are trying to mark read only. If we do then we can mark this block group as read only. Reviewed-by: Qu Wenruo Signed-off-by: Josef Bacik Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Anand Jain --- fs/btrfs/block-group.c | 38 ++ fs/btrfs/space-info.c | 18 ++ fs/btrfs/space-info.h | 3 +++ 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c index b167649f5f5d..ace49a999ece 100644 --- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -1186,7 +1186,6 @@ static int inc_block_group_ro(struct btrfs_block_group_cache *cache, int force) { struct btrfs_space_info *sinfo = cache->space_info; u64 num_bytes; - u64 sinfo_used; u64 min_allocable_bytes; int ret = -ENOSPC; @@ -1213,20 +1212,38 @@ static int inc_block_group_ro(struct btrfs_block_group_cache *cache, int force) num_bytes = cache->key.offset - cache->reserved - cache->pinned - cache->bytes_super - btrfs_block_group_used(&cache->item); - sinfo_used = btrfs_space_info_used(sinfo, true); /* -* sinfo_used + num_bytes should always <= sinfo->total_bytes. -* -* Here we make sure if we mark this bg RO, we still have enough -* free space as buffer (if min_allocable_bytes is not 0). +* Data never overcommits, even in mixed mode, so do just the straight +* check of left over space in how much we have allocated. */ - if (sinfo_used + num_bytes + min_allocable_bytes <= - sinfo->total_bytes) { + if (force) { + ret = 0; + } else if (sinfo->flags & BTRFS_BLOCK_GROUP_DATA) { + u64 sinfo_used = btrfs_space_info_used(sinfo, true); + + /* +* Here we make sure if we mark this bg RO, we still have enough +* free space as buffer. +*/ + if (sinfo_used + num_bytes <= sinfo->total_bytes) + ret = 0; + } else { + /* +* We overcommit metadata, so we need to do the +* btrfs_can_overcommit check here, and we need to pass in +* BTRFS_RESERVE_NO_FLUSH to give ourselves the most amount of +* leeway to allow us to mark this block group as read only. +*/ + if (btrfs_can_overcommit(cache->fs_info, sinfo, num_bytes, +BTRFS_RESERVE_NO_FLUSH)) + ret = 0; + } + + if (!ret) { sinfo->bytes_readonly += num_bytes; cache->ro++; list_add_tail(&cache->ro_list, &sinfo->ro_bgs); - ret = 0; } out: spin_unlock(&cache->lock); @@ -1235,9 +1252,6 @@ static int inc_block_group_ro(struct btrfs_block_group_cache *cache, int force) btrfs_info(cache->fs_info, "unable to make block group %llu ro", cache->key.objectid); - btrfs_info(cache->fs_info, - "sinfo_used=%llu bg_num_bytes=%llu min_allocable=%llu", - sinfo_used, num_bytes, min_allocable_bytes); btrfs_dump_space_info(cache->fs_info, cache->space_info, 0, 0); } return ret; diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index e19e538d05f9..90500b6c41fc 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -160,9 +160,9 @@ static inline u64 calc_global_rsv_need_space(struct btrfs_block_rsv *global) return (global->size << 1); } -static int can_overcommit(struct btrfs_fs_info *fs_info, - struct btrfs_space_info *space_info, u64 bytes, - enum btrfs_reserve_flush_enum flush) +int btrfs_can_overcommit(struct btrfs_fs_info *fs_info, +struct btrfs_space_info *space_info, u64 bytes, +enum btrfs_reserve_flush_enum flush) { u64 profile; u64 avail; @@ -227,7 +227,8 @@ void btrfs_try_granting_tickets(struct btrfs_fs_info *fs_info, /* Check and see if our ticket can be satisified now. */ if ((used + ticket->bytes <= space_info->total_bytes) || - c
Re: [PATCH 1/2] soc: samsung: exynos-pmu: instantiate clkout driver as MFD
Quoting Krzysztof Kozlowski (2020-10-01 09:56:45) > The Exynos clock output (clkout) driver uses same register address space > (Power Management Unit address space) as Exynos PMU driver and same set > of compatibles. It was modeled as clock provider instantiated with > CLK_OF_DECLARE_DRIVE(). > > This however brings ordering problems and lack of probe deferral, > therefore clkout driver should be converted to a regular module and > instantiated as a child of PMU driver to be able to use existing > compatibles and address space. > > Signed-off-by: Krzysztof Kozlowski > --- Reviewed-by: Stephen Boyd
Re: [PATCH 2/2] clk: samsung: exynos-clkout: convert to module driver
Quoting Krzysztof Kozlowski (2020-10-01 09:56:46) > diff --git a/drivers/clk/samsung/clk-exynos-clkout.c > b/drivers/clk/samsung/clk-exynos-clkout.c > index 34ccb1d23bc3..68af082d4716 100644 > --- a/drivers/clk/samsung/clk-exynos-clkout.c > +++ b/drivers/clk/samsung/clk-exynos-clkout.c > @@ -28,41 +31,103 @@ struct exynos_clkout { [...] > + if (!match) { > + dev_err(dev, "cannot match parent device\n"); > + return -EINVAL; > + } > + variant = match->data; > + > + *mux_mask = variant->mux_mask; > + dev_err(dev, "MATCH: %x\n", variant->mux_mask); Is this a debug print? > + > + return 0; > +} >
[PATCH v4 0/5] clk: rockchip: Support for some new features
1. Support for some new features 2. fix up some error Chang in V4: [PATCH v3 1/5] : Update the commit message. [PATCH v3 2/5] : Update the commit message. Chang in V3: [PATCH v2 3/6] : It's been merged So rebased and resubmit. Chang in V2: [PATCH v2 5/6] : fix up the Register error, and add delay. Elaine Zhang (5): clk: rockchip: Add supprot to limit input rate for fractional divider clk: rockchip: fix up the frac clk get rate error clk: rockchip: add a clock-type for muxes based in the pmugrf clk: rockchip: add pll up and down when change pll freq clk: rockchip: support pll setting by auto drivers/clk/rockchip/clk-pll.c| 236 -- drivers/clk/rockchip/clk-px30.c | 29 ++-- drivers/clk/rockchip/clk-rk3036.c | 13 +- drivers/clk/rockchip/clk-rk3128.c | 15 +- drivers/clk/rockchip/clk-rk3188.c | 24 +-- drivers/clk/rockchip/clk-rk3228.c | 18 ++- drivers/clk/rockchip/clk-rk3288.c | 19 ++- drivers/clk/rockchip/clk-rk3308.c | 46 +++--- drivers/clk/rockchip/clk-rk3328.c | 17 ++- drivers/clk/rockchip/clk-rk3368.c | 17 ++- drivers/clk/rockchip/clk-rk3399.c | 32 ++-- drivers/clk/rockchip/clk-rv1108.c | 14 +- drivers/clk/rockchip/clk.c| 39 - drivers/clk/rockchip/clk.h| 27 +++- include/linux/clk-provider.h | 2 + 15 files changed, 422 insertions(+), 126 deletions(-) -- 2.17.1
[PATCH v4 2/5] clk: rockchip: fix up the frac clk get rate error
support fractional divider with one level and two level parent clock .i.e: normal fractional divider is: |--\ ---[GPLL]---| \ |--\ ---[CPLL]---|mux|--[GATE]--[DIV]---| \ ---[NPLL]---| /| |mux|--[GATE]--[UART0] |--/ |--[GATE]--[FRACDIV]--| / |--/ but rk3399 uart is special: |--\ ---[GPLL]---| \ |--\ ---[CPLL]---|mux|--|--[GATE]--[DIV]---| \ ---[NPLL]---| / || |mux|--[GATE]--[UART1] |--/ ||--[GATE]--[FRACDIV]--| / | |--/ | | |--\ |--[GATE]--[DIV]---| \ || |mux|--[GATE]--[UART2] ||--[GATE]--[FRACDIV]--| / | |--/ | | |--\ |--[GATE]--[DIV]---| \ | |mux|--[GATE]--[UART3] |--[GATE]--[FRACDIV]--| / |--/ The special fractional divider, there are two levels of clock between FRACDIV and PLL. Signed-off-by: Elaine Zhang --- drivers/clk/rockchip/clk.c | 19 --- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index fac5a4a3f5c3..8f77c3f9fab7 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -190,16 +190,21 @@ static void rockchip_fractional_approximation(struct clk_hw *hw, if (((rate * 20 > p_rate) && (p_rate % rate != 0)) || (fd->max_prate && fd->max_prate < p_rate)) { p_parent = clk_hw_get_parent(clk_hw_get_parent(hw)); - p_parent_rate = clk_hw_get_rate(p_parent); - *parent_rate = p_parent_rate; - if (fd->max_prate && p_parent_rate > fd->max_prate) { - div = DIV_ROUND_UP(p_parent_rate, fd->max_prate); - *parent_rate = p_parent_rate / div; + if (!p_parent) { + *parent_rate = p_rate; + } else { + p_parent_rate = clk_hw_get_rate(p_parent); + *parent_rate = p_parent_rate; + if (fd->max_prate && p_parent_rate > fd->max_prate) { + div = DIV_ROUND_UP(p_parent_rate, + fd->max_prate); + *parent_rate = p_parent_rate / div; + } } if (*parent_rate < rate * 20) { - pr_err("%s parent_rate(%ld) is low than rate(%ld)*20, fractional div is not allowed\n", - clk_hw_get_name(hw), *parent_rate, rate); + pr_warn("%s p_rate(%ld) is low than rate(%ld)*20, use integer or half-div\n", + clk_hw_get_name(hw), *parent_rate, rate); *m = 0; *n = 1; return; -- 2.17.1
[PATCH v4 5/5] clk: rockchip: support pll setting by auto
If setting freq is not support in rockchip_pll_rate_table, It can calculate and set pll params by auto. Signed-off-by: Elaine Zhang --- drivers/clk/rockchip/clk-pll.c | 215 ++--- 1 file changed, 200 insertions(+), 15 deletions(-) diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 8adc6f54a605..e8ca86f5b7d1 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "clk.h" #define PLL_MODE_MASK 0x3 @@ -47,6 +48,198 @@ struct rockchip_clk_pll { #define to_rockchip_clk_pll_nb(nb) \ container_of(nb, struct rockchip_clk_pll, clk_nb) +#define MHZ(1000UL * 1000UL) +#define KHZ(1000UL) + +/* CLK_PLL_TYPE_RK3066_AUTO type ops */ +#define PLL_FREF_MIN (269 * KHZ) +#define PLL_FREF_MAX (2200 * MHZ) + +#define PLL_FVCO_MIN (440 * MHZ) +#define PLL_FVCO_MAX (2200 * MHZ) + +#define PLL_FOUT_MIN (27500 * KHZ) +#define PLL_FOUT_MAX (2200 * MHZ) + +#define PLL_NF_MAX (4096) +#define PLL_NR_MAX (64) +#define PLL_NO_MAX (16) + +/* CLK_PLL_TYPE_RK3036/3366/3399_AUTO type ops */ +#define MIN_FOUTVCO_FREQ (800 * MHZ) +#define MAX_FOUTVCO_FREQ (2000 * MHZ) + +static struct rockchip_pll_rate_table auto_table; + +static struct rockchip_pll_rate_table *rk_pll_rate_table_get(void) +{ + return &auto_table; +} + +static int rockchip_pll_clk_set_postdiv(unsigned long fout_hz, + u32 *postdiv1, + u32 *postdiv2, + u32 *foutvco) +{ + unsigned long freq; + + if (fout_hz < MIN_FOUTVCO_FREQ) { + for (*postdiv1 = 1; *postdiv1 <= 7; (*postdiv1)++) { + for (*postdiv2 = 1; *postdiv2 <= 7; (*postdiv2)++) { + freq = fout_hz * (*postdiv1) * (*postdiv2); + if (freq >= MIN_FOUTVCO_FREQ && + freq <= MAX_FOUTVCO_FREQ) { + *foutvco = freq; + return 0; + } + } + } + pr_err("CANNOT FIND postdiv1/2 to make fout in range from 800M to 2000M,fout = %lu\n", + fout_hz); + } else { + *postdiv1 = 1; + *postdiv2 = 1; + } + return 0; +} + +static struct rockchip_pll_rate_table * +rockchip_pll_clk_set_by_auto(struct rockchip_clk_pll *pll, +unsigned long fin_hz, +unsigned long fout_hz) +{ + struct rockchip_pll_rate_table *rate_table = rk_pll_rate_table_get(); + /* FIXME set postdiv1/2 always 1*/ + u32 foutvco = fout_hz; + u64 fin_64, frac_64; + u32 f_frac, postdiv1, postdiv2; + unsigned long clk_gcd = 0; + + if (fin_hz == 0 || fout_hz == 0 || fout_hz == fin_hz) + return NULL; + + rockchip_pll_clk_set_postdiv(fout_hz, &postdiv1, &postdiv2, &foutvco); + rate_table->postdiv1 = postdiv1; + rate_table->postdiv2 = postdiv2; + rate_table->dsmpd = 1; + + if (fin_hz / MHZ * MHZ == fin_hz && fout_hz / MHZ * MHZ == fout_hz) { + fin_hz /= MHZ; + foutvco /= MHZ; + clk_gcd = gcd(fin_hz, foutvco); + rate_table->refdiv = fin_hz / clk_gcd; + rate_table->fbdiv = foutvco / clk_gcd; + + rate_table->frac = 0; + + pr_debug("fin = %lu, fout = %lu, clk_gcd = %lu, refdiv = %u, fbdiv = %u, postdiv1 = %u, postdiv2 = %u, frac = %u\n", +fin_hz, fout_hz, clk_gcd, rate_table->refdiv, +rate_table->fbdiv, rate_table->postdiv1, +rate_table->postdiv2, rate_table->frac); + } else { + pr_debug("frac div running, fin_hz = %lu, fout_hz = %lu, fin_INT_mhz = %lu, fout_INT_mhz = %lu\n", +fin_hz, fout_hz, +fin_hz / MHZ * MHZ, +fout_hz / MHZ * MHZ); + pr_debug("frac get postdiv1 = %u, postdiv2 = %u, foutvco = %u\n", +rate_table->postdiv1, rate_table->postdiv2, foutvco); + clk_gcd = gcd(fin_hz / MHZ, foutvco / MHZ); + rate_table->refdiv = fin_hz / MHZ / clk_gcd; + rate_table->fbdiv = foutvco / MHZ / clk_gcd; + pr_debug("frac get refdiv = %u, fbdiv = %u\n", +rate_table->refdiv, rate_table->fbdiv); + + rate_table->frac = 0; + + f_frac = (foutvco % MHZ); + fin_64 = fin_hz; + do_div(fin_64, (u64)rate_table->refdiv); +
Re: [PATCH 1/7] clk: qcom: clk-alpha-pll: Add support for Stromer PLLs
Can you check your get_maintainers script invocation? Not sure why arm64 maintainers are Cced on a clk patch. Quoting Varadarajan Narayanan (2020-09-27 22:15:34) > Add programming sequence support for managing the Stromer > PLLs. > > Signed-off-by: Varadarajan Narayanan > --- > drivers/clk/qcom/clk-alpha-pll.c | 156 > ++- > drivers/clk/qcom/clk-alpha-pll.h | 5 ++ > 2 files changed, 160 insertions(+), 1 deletion(-) > > diff --git a/drivers/clk/qcom/clk-alpha-pll.c > b/drivers/clk/qcom/clk-alpha-pll.c > index 26139ef..ce3257f 100644 > --- a/drivers/clk/qcom/clk-alpha-pll.c > +++ b/drivers/clk/qcom/clk-alpha-pll.c > @@ -116,6 +116,19 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { > [PLL_OFF_OPMODE] = 0x38, > [PLL_OFF_ALPHA_VAL] = 0x40, > }, > + Nitpick: Drop this newline. > + [CLK_ALPHA_PLL_TYPE_STROMER] = { > + [PLL_OFF_L_VAL] = 0x08, > + [PLL_OFF_ALPHA_VAL] = 0x10, > + [PLL_OFF_ALPHA_VAL_U] = 0x14, > + [PLL_OFF_USER_CTL] = 0x18, > + [PLL_OFF_USER_CTL_U] = 0x1c, > + [PLL_OFF_CONFIG_CTL] = 0x20, > + [PLL_OFF_CONFIG_CTL_U] = 0xff, > + [PLL_OFF_TEST_CTL] = 0x30, > + [PLL_OFF_TEST_CTL_U] = 0x34, > + [PLL_OFF_STATUS] = 0x28, > + }, > }; > EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); > > @@ -127,6 +140,8 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); > #define ALPHA_BITWIDTH 32U > #define ALPHA_SHIFT(w) min(w, ALPHA_BITWIDTH) > > +#definePLL_STATUS_REG_SHIFT8 This should have an ALPHA_ prefix. > + > #define PLL_HUAYRA_M_WIDTH 8 > #define PLL_HUAYRA_M_SHIFT 8 > #define PLL_HUAYRA_M_MASK 0xff > @@ -240,14 +255,143 @@ void clk_alpha_pll_configure(struct clk_alpha_pll > *pll, struct regmap *regmap, > mask |= config->pre_div_mask; > mask |= config->post_div_mask; > mask |= config->vco_mask; > + mask |= config->alpha_en_mask; > + mask |= config->alpha_mode_mask; > > regmap_update_bits(regmap, PLL_USER_CTL(pll), mask, val); > > + /* Stromer APSS PLL does not enable LOCK_DET by default, so enable it > */ > + val_u = config->status_reg_val << PLL_STATUS_REG_SHIFT; > + val_u |= config->lock_det; > + > + mask_u = config->status_reg_mask; > + mask_u |= config->lock_det; > + > + if (val_u != 0) if (val_u) is more canonical. > + regmap_update_bits(regmap, PLL_USER_CTL_U(pll), mask_u, > val_u); > + > + if (config->test_ctl_val != 0) Same comment > + regmap_write(regmap, PLL_TEST_CTL(pll), config->test_ctl_val); > + > + if (config->test_ctl_hi_val != 0) Same comment > + regmap_write(regmap, PLL_TEST_CTL_U(pll), > config->test_ctl_hi_val); > + > if (pll->flags & SUPPORTS_FSM_MODE) > qcom_pll_set_fsm_mode(regmap, PLL_MODE(pll), 6, 0); > } > EXPORT_SYMBOL_GPL(clk_alpha_pll_configure); > > +static unsigned long > +alpha_pll_stromer_calc_rate(u64 prate, u32 l, u64 a) > +{ > + return (prate * l) + ((prate * a) >> ALPHA_REG_BITWIDTH); Is this not already in this file? Why can't we use alpha_pll_calc_rate()? > +} > + > +static unsigned long > +alpha_pll_stromer_round_rate(unsigned long rate, unsigned long prate, u32 > *l, u64 *a) > +{ > + u64 remainder; > + u64 quotient; > + > + quotient = rate; > + remainder = do_div(quotient, prate); > + *l = quotient; > + > + if (!remainder) { > + *a = 0; > + return rate; > + } > + > + quotient = remainder << ALPHA_REG_BITWIDTH; > + > + remainder = do_div(quotient, prate); > + > + if (remainder) > + quotient++; > + > + *a = quotient; > + return alpha_pll_stromer_calc_rate(prate, *l, *a); > +} > + > +static unsigned long > +clk_alpha_pll_stromer_recalc_rate(struct clk_hw *hw, unsigned long > parent_rate) > +{ > + u32 l, low, high, ctl; > + u64 a = 0, prate = parent_rate; > + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); > + > + regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); > + > + regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl); > + if (ctl & PLL_ALPHA_EN) { > + regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &low); > + regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), > + &high); > + a = (u64)high << ALPHA_BITWIDTH | low; > + } > + > + return alpha_pll_stromer_calc_rate(prate, l, a); > +} > + > +static int clk_alpha_pll_stromer_determine_rate(struct clk_hw *hw, > +struct clk_rate_request *req) > +{ > + unsigned long rate = req->rate; > + u32 l; > + u64 a; > + > + rate = alpha_pll_stromer_round_rate(ra
[PATCH v4 3/5] clk: rockchip: add a clock-type for muxes based in the pmugrf
Rockchip socs often have some tiny number of muxes not controlled from the core clock controller but through bits set in the pmugrf. Use MUXPMUGRF() to cover this special clock-type. Signed-off-by: Elaine Zhang --- drivers/clk/rockchip/clk.c | 9 + drivers/clk/rockchip/clk.h | 17 + 2 files changed, 26 insertions(+) diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 8f77c3f9fab7..4f238f2851ac 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -407,6 +407,8 @@ struct rockchip_clk_provider * __init rockchip_clk_init(struct device_node *np, ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node, "rockchip,grf"); + ctx->pmugrf = syscon_regmap_lookup_by_phandle(ctx->cru_node, + "rockchip,pmugrf"); return ctx; @@ -482,6 +484,13 @@ void __init rockchip_clk_register_branches( list->mux_shift, list->mux_width, list->mux_flags); break; + case branch_muxpmugrf: + clk = rockchip_clk_register_muxgrf(list->name, + list->parent_names, list->num_parents, + flags, ctx->pmugrf, list->muxdiv_offset, + list->mux_shift, list->mux_width, + list->mux_flags); + break; case branch_divider: if (list->div_table) clk = clk_register_divider_table(NULL, diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 0d401ce09a54..ae059b7744f9 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -238,6 +238,7 @@ struct rockchip_clk_provider { struct clk_onecell_data clk_data; struct device_node *cru_node; struct regmap *grf; + struct regmap *pmugrf; spinlock_t lock; }; @@ -390,6 +391,7 @@ enum rockchip_clk_branch_type { branch_composite, branch_mux, branch_muxgrf, + branch_muxpmugrf, branch_divider, branch_fraction_divider, branch_gate, @@ -662,6 +664,21 @@ struct rockchip_clk_branch { .gate_offset= -1, \ } +#define MUXPMUGRF(_id, cname, pnames, f, o, s, w, mf) \ + { \ + .id = _id, \ + .branch_type= branch_muxpmugrf, \ + .name = cname,\ + .parent_names = pnames, \ + .num_parents= ARRAY_SIZE(pnames), \ + .flags = f,\ + .muxdiv_offset = o,\ + .mux_shift = s,\ + .mux_width = w,\ + .mux_flags = mf, \ + .gate_offset= -1, \ + } + #define DIV(_id, cname, pname, f, o, s, w, df) \ { \ .id = _id, \ -- 2.17.1
[PATCH v4 4/5] clk: rockchip: add pll up and down when change pll freq
set pll sequence: ->set pll to slow mode or other plls ->set pll down ->set pll params ->set pll up ->wait pll lock status ->set pll to normal mode To slove the system error: wait_pll_lock: timeout waiting for pll to lock pll_set_params: pll update unsucessful, trying to restore old params Signed-off-by: Elaine Zhang --- drivers/clk/rockchip/clk-pll.c | 21 + 1 file changed, 21 insertions(+) diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 4c6c9167ef50..8adc6f54a605 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -210,6 +210,11 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll, rate_change_remuxed = 1; } + /* set pll power down */ + writel(HIWORD_UPDATE(RK3036_PLLCON1_PWRDOWN, +RK3036_PLLCON1_PWRDOWN, 0), + pll->reg_base + RK3036_PLLCON(1)); + /* update pll values */ writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3036_PLLCON0_FBDIV_MASK, RK3036_PLLCON0_FBDIV_SHIFT) | @@ -231,6 +236,11 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll, pllcon |= rate->frac << RK3036_PLLCON2_FRAC_SHIFT; writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2)); + /* set pll power up */ + writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0), + pll->reg_base + RK3036_PLLCON(1)); + udelay(1); + /* wait for the pll to lock */ ret = rockchip_rk3036_pll_wait_lock(pll); if (ret) { @@ -692,6 +702,11 @@ static int rockchip_rk3399_pll_set_params(struct rockchip_clk_pll *pll, rate_change_remuxed = 1; } + /* set pll power down */ + writel(HIWORD_UPDATE(RK3399_PLLCON3_PWRDOWN, +RK3399_PLLCON3_PWRDOWN, 0), + pll->reg_base + RK3399_PLLCON(3)); + /* update pll values */ writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3399_PLLCON0_FBDIV_MASK, RK3399_PLLCON0_FBDIV_SHIFT), @@ -715,6 +730,12 @@ static int rockchip_rk3399_pll_set_params(struct rockchip_clk_pll *pll, RK3399_PLLCON3_DSMPD_SHIFT), pll->reg_base + RK3399_PLLCON(3)); + /* set pll power up */ + writel(HIWORD_UPDATE(0, +RK3399_PLLCON3_PWRDOWN, 0), + pll->reg_base + RK3399_PLLCON(3)); + udelay(1); + /* wait for the pll to lock */ ret = rockchip_rk3399_pll_wait_lock(pll); if (ret) { -- 2.17.1
[PATCH v4 1/5] clk: rockchip: Add supprot to limit input rate for fractional divider
>From Rockchips fractional divider usage, some clocks can be generated by fractional divider, but the input clock frequency of fractional divider should be less than a specified value. .i.e: |--\ ---[GPLL]---| \ |--\ ---[CPLL]---|mux|--[GATE]--[DIV]---| \ ---[NPLL]---| /| |mux|--[GATE]-- |--/ |--[GATE]--[FRACDIV]--| / |--/ The FRACDIV frequency is designed to be only 300M(Different SOC implementations are different).But the GPLL or CPLL may be 1200M. Must be added to limit to ensure that the design is not exceeded. Signed-off-by: Finley Xiao Signed-off-by: Elaine Zhang --- drivers/clk/rockchip/clk-px30.c | 29 +-- drivers/clk/rockchip/clk-rk3036.c | 13 + drivers/clk/rockchip/clk-rk3128.c | 15 ++ drivers/clk/rockchip/clk-rk3188.c | 24 +--- drivers/clk/rockchip/clk-rk3228.c | 18 +++- drivers/clk/rockchip/clk-rk3288.c | 19 +++-- drivers/clk/rockchip/clk-rk3308.c | 46 +-- drivers/clk/rockchip/clk-rk3328.c | 17 +++- drivers/clk/rockchip/clk-rk3368.c | 17 +++- drivers/clk/rockchip/clk-rk3399.c | 32 - drivers/clk/rockchip/clk-rv1108.c | 14 ++ drivers/clk/rockchip/clk.c| 21 -- drivers/clk/rockchip/clk.h| 10 +-- include/linux/clk-provider.h | 2 ++ 14 files changed, 168 insertions(+), 109 deletions(-) diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c index 6fb9c98b7d24..f075eb922bab 100644 --- a/drivers/clk/rockchip/clk-px30.c +++ b/drivers/clk/rockchip/clk-px30.c @@ -13,6 +13,7 @@ #include "clk.h" #define PX30_GRF_SOC_STATUS0 0x480 +#define PX30_FRAC_MAX_PRATE6 enum px30_plls { apll, dpll, cpll, npll, apll_b_h, apll_b_l, @@ -424,7 +425,7 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { COMPOSITE_FRACMUX(0, "dclk_vopb_frac", "dclk_vopb_src", CLK_SET_RATE_PARENT, PX30_CLKSEL_CON(6), 0, PX30_CLKGATE_CON(2), 3, GFLAGS, - &px30_dclk_vopb_fracmux), + &px30_dclk_vopb_fracmux, 0), GATE(DCLK_VOPB, "dclk_vopb", "dclk_vopb_mux", CLK_SET_RATE_PARENT, PX30_CLKGATE_CON(2), 4, GFLAGS), COMPOSITE(0, "dclk_vopl_src", mux_npll_cpll_p, 0, @@ -433,7 +434,7 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { COMPOSITE_FRACMUX(0, "dclk_vopl_frac", "dclk_vopl_src", CLK_SET_RATE_PARENT, PX30_CLKSEL_CON(9), 0, PX30_CLKGATE_CON(2), 7, GFLAGS, - &px30_dclk_vopl_fracmux), + &px30_dclk_vopl_fracmux, 0), GATE(DCLK_VOPL, "dclk_vopl", "dclk_vopl_mux", CLK_SET_RATE_PARENT, PX30_CLKGATE_CON(2), 8, GFLAGS), @@ -591,7 +592,7 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { COMPOSITE_FRACMUX(0, "clk_pdm_frac", "clk_pdm_src", CLK_SET_RATE_PARENT, PX30_CLKSEL_CON(27), 0, PX30_CLKGATE_CON(9), 10, GFLAGS, - &px30_pdm_fracmux), + &px30_pdm_fracmux, PX30_FRAC_MAX_PRATE), GATE(SCLK_PDM, "clk_pdm", "clk_pdm_mux", CLK_SET_RATE_PARENT, PX30_CLKGATE_CON(9), 11, GFLAGS), @@ -601,7 +602,7 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { COMPOSITE_FRACMUX(0, "clk_i2s0_tx_frac", "clk_i2s0_tx_src", CLK_SET_RATE_PARENT, PX30_CLKSEL_CON(29), 0, PX30_CLKGATE_CON(9), 13, GFLAGS, - &px30_i2s0_tx_fracmux), + &px30_i2s0_tx_fracmux, PX30_FRAC_MAX_PRATE), COMPOSITE_NODIV(SCLK_I2S0_TX, "clk_i2s0_tx", mux_i2s0_tx_rx_p, CLK_SET_RATE_PARENT, PX30_CLKSEL_CON(28), 12, 1, MFLAGS, PX30_CLKGATE_CON(9), 14, GFLAGS), @@ -617,7 +618,7 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { COMPOSITE_FRACMUX(0, "clk_i2s0_rx_frac", "clk_i2s0_rx_src", CLK_SET_RATE_PARENT, PX30_CLKSEL_CON(59), 0, PX30_CLKGATE_CON(17), 1, GFLAGS, - &px30_i2s0_rx_fracmux), + &px30_i2s0_rx_fracmux, PX30_FRAC_MAX_PRATE), COMPOSITE_NODIV(SCLK_I2S0_RX, "clk_i2s0_rx", mux_i2s0_rx_tx_p, CLK_SET_RATE_PARENT, PX30_CLKSEL_CON(58), 12, 1, MFLAGS, PX30_CLKGATE_CON(17), 2, GFLAGS), @@ -633,7 +634,7 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { COMPOSITE_FRACMUX(0, "clk_i2s1_frac", "clk_i2s1_src", CLK_SET_RATE_PAREN
Re: [PATCH v3] Documentation: Chinese translation of Documentation/arm64/hugetlbpage.rst
Reviewed-by: Alex Shi 在 2020/10/14 上午10:20, Bailu Lin 写道: > This is a Chinese translated version of > Documentation/arm64/hugetlbpage.rst > > Signed-off-by: Bailu Lin > --- > Changes in v3: > - Modify a translation as Alex sugguested. > Changes in v2: > - Fix Sphinx 2.4.4's waring by increasing underline' size. > --- > Documentation/arm64/hugetlbpage.rst | 2 + > .../translations/zh_CN/arm64/hugetlbpage.rst | 45 +++ > .../translations/zh_CN/arm64/index.rst| 1 + > 3 files changed, 48 insertions(+) > create mode 100644 Documentation/translations/zh_CN/arm64/hugetlbpage.rst > > diff --git a/Documentation/arm64/hugetlbpage.rst > b/Documentation/arm64/hugetlbpage.rst > index b44f939e5210..a110124c11e3 100644 > --- a/Documentation/arm64/hugetlbpage.rst > +++ b/Documentation/arm64/hugetlbpage.rst > @@ -1,3 +1,5 @@ > +.. _hugetlbpage_index: > + > > HugeTLBpage on ARM64 > > diff --git a/Documentation/translations/zh_CN/arm64/hugetlbpage.rst > b/Documentation/translations/zh_CN/arm64/hugetlbpage.rst > new file mode 100644 > index ..13304d269d0b > --- /dev/null > +++ b/Documentation/translations/zh_CN/arm64/hugetlbpage.rst > @@ -0,0 +1,45 @@ > +.. include:: ../disclaimer-zh_CN.rst > + > +:Original: :ref:`Documentation/arm64/hugetlbpage.rst ` > + > +Translator: Bailu Lin > + > += > +ARM64中的 HugeTLBpage > += > + > +大页依靠有效利用 TLBs 来提高地址翻译的性能。这取决于以下 > +两点 - > + > + - 大页的大小 > + - TLBs 支持的条目大小 > + > +ARM64 接口支持2种大页方式。 > + > +1) pud/pmd 级别的块映射 > +--- > + > +这是常规大页,他们的 pmd 或 pud 页面表条目指向一个内存块。 > +不管 TLB 中支持的条目大小如何,块映射可以减少翻译大页地址 > +所需遍历的页表深度。 > + > +2) 使用连续位 > +- > + > +架构中转换页表条目(D4.5.3, ARM DDI 0487C.a)中提供一个连续 > +位告诉 MMU 这个条目是一个连续条目集的一员,它可以被缓存在单 > +个 TLB 条目中。 > + > +在 Linux 中连续位用来增加 pmd 和 pte(最后一级)级别映射的大 > +小。受支持的连续页表条目数量因页面大小和页表级别而异。 > + > + > +支持以下大页尺寸配置 - > + > + == === > + - CONT PTEPMDCONT PMDPUD > + == === > + 4K: 64K 2M 32M 1G > + 16K: 2M32M 1G > + 64K: 2M 512M 16G > + == === > diff --git a/Documentation/translations/zh_CN/arm64/index.rst > b/Documentation/translations/zh_CN/arm64/index.rst > index 646ed1f7aea3..e31a6090384d 100644 > --- a/Documentation/translations/zh_CN/arm64/index.rst > +++ b/Documentation/translations/zh_CN/arm64/index.rst > @@ -14,3 +14,4 @@ ARM64 架构 > :maxdepth: 2 > > amu > +hugetlbpage >
Re: [PATCH v6 4/4] mmc: mediatek: Add subsys clock control for MT8192 msdc
On Tue, 2020-10-13 at 17:10 +0200, Matthias Brugger wrote: > > On 12/10/2020 14:45, Wenbin Mei wrote: > > MT8192 msdc is an independent sub system, we need control more bus > > clocks for it. > > Add support for the additional subsys clocks to allow it to be > > configured appropriately. > > > > Signed-off-by: Wenbin Mei > > --- > > drivers/mmc/host/mtk-sd.c | 74 +-- > > 1 file changed, 56 insertions(+), 18 deletions(-) > > > > diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c > > index a704745e5882..c7df7510f120 100644 > > --- a/drivers/mmc/host/mtk-sd.c > > +++ b/drivers/mmc/host/mtk-sd.c > [...] > > +static int msdc_of_clock_parse(struct platform_device *pdev, > > + struct msdc_host *host) > > +{ > > + int ret; > > + > > + host->src_clk = devm_clk_get(&pdev->dev, "source"); > > + if (IS_ERR(host->src_clk)) > > + return PTR_ERR(host->src_clk); > > + > > + host->h_clk = devm_clk_get(&pdev->dev, "hclk"); > > + if (IS_ERR(host->h_clk)) > > + return PTR_ERR(host->h_clk); > > + > > + host->bus_clk = devm_clk_get_optional(&pdev->dev, "bus_clk"); > > + if (IS_ERR(host->bus_clk)) > > + host->bus_clk = NULL; > > + > > + /*source clock control gate is optional clock*/ > > + host->src_clk_cg = devm_clk_get_optional(&pdev->dev, "source_cg"); > > + if (IS_ERR(host->src_clk_cg)) > > + host->src_clk_cg = NULL; > > + > > + host->sys_clk_cg = devm_clk_get_optional(&pdev->dev, "sys_cg"); > > + if (IS_ERR(host->sys_clk_cg)) > > + host->sys_clk_cg = NULL; > > + > > + /* If present, always enable for this clock gate */ > > + clk_prepare_enable(host->sys_clk_cg); > > + > > + host->bulk_clks[0].id = "pclk_cg"; > > + host->bulk_clks[1].id = "axi_cg"; > > + host->bulk_clks[2].id = "ahb_cg"; > > That looks at least suspicious. The pointers of id point to some strings > defined > in the function. Aren't they out of scope once msdc_of_clock_parse() has > returned? > These constants are not in stack range, so they will not be lost. And I have confirmed it after msdc_of_clock_parse() has returned, these ids still exist. > Regards, > Matthias
Re: [PATCH 3/7] clk: qcom: Add Global Clock controller (GCC) driver for IPQ5018
Quoting Varadarajan Narayanan (2020-09-27 22:15:36) > diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig > index 0583273..d1a2504 100644 > --- a/drivers/clk/qcom/Kconfig > +++ b/drivers/clk/qcom/Kconfig > @@ -155,6 +155,14 @@ config IPQ_GCC_8074 > i2c, USB, SD/eMMC, etc. Select this for the root clock > of ipq8074. > > +config IPQ_GCC_5018 > + tristate "IPQ5018 Global Clock Controller" > + help > +Support for global clock controller on ipq5018 devices. > +Say Y if you want to use peripheral devices such as UART, SPI, > +i2c, USB, SD/eMMC, etc. Select this for the root clock > +of ipq5018. What is the root clock of ipq5018? Please drop that last sentence. > + > config MSM_GCC_8660 > tristate "MSM8660 Global Clock Controller" > help > diff --git a/drivers/clk/qcom/gcc-ipq5018.c b/drivers/clk/qcom/gcc-ipq5018.c > new file mode 100644 > index ..9056386 > --- /dev/null > +++ b/drivers/clk/qcom/gcc-ipq5018.c > @@ -0,0 +1,3833 @@ > +// SPDX-License-Identifier: GPL-2.0+ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include Why is this attached to dt-bindings? Please remove that newline above and move this away from dt-bindings below. > +#include > +#include > + > +#include "common.h" > +#include "clk-regmap.h" > +#include "clk-pll.h" > +#include "clk-rcg.h" > +#include "clk-branch.h" > +#include "clk-alpha-pll.h" > +#include "clk-regmap-divider.h" > +#include "clk-regmap-mux.h" > +#include "reset.h" > + > +#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } This is in clk-rcg.h already. > + > +static const char * const gcc_usb3phy_0_cc_pipe_clk_xo[] = { > + "usb3phy_0_cc_pipe_clk", > + "xo", > +}; All these names structures need to change, see next comment. > + > +static struct clk_rcg2 apss_ahb_clk_src = { > + .cmd_rcgr = 0x46000, > + .mnd_width = 0, > + .hid_width = 5, > + .freq_tbl = ftbl_apss_ahb_clk_src, > + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, > + .clkr.hw.init = &(struct clk_init_data){ > + .name = "apss_ahb_clk_src", > + .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, > + .num_parents = 3, Please migrate to the new way of specifying clks with clk_init_data::clk_parent_data > + .ops = &clk_rcg2_ops, > + .flags = CLK_IS_CRITICAL | CLK_IGNORE_UNUSED, Why is it critical and ignore unused? Do you need this clk to be here at all? Can we just enable it when this driver probes with a register write and then ignore it from there on out? > + }, > +}; > + > +static struct clk_regmap_div apss_ahb_postdiv_clk_src = { > + .reg = 0x46018, > + .shift = 4, > + .width = 4, > + .clkr = { > + .hw.init = &(struct clk_init_data){ > + .name = "apss_ahb_postdiv_clk_src", > + .parent_names = (const char *[]){ > + "apss_ahb_clk_src" > + }, > + .num_parents = 1, > + .ops = &clk_regmap_div_ops, > + }, > + }, > +}; > + [...] > + > +static struct clk_branch gcc_qdss_dap_clk = { > + .halt_reg = 0x29084, > + .clkr = { > + .enable_reg = 0x29084, > + .enable_mask = BIT(0), > + .hw.init = &(struct clk_init_data){ > + .name = "gcc_qdss_dap_clk", > + .parent_names = (const char *[]){ > + "qdss_tsctr_clk_src" > + }, > + .num_parents = 1, > + .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, Whenever CLK_IS_CRITICAL is there please document why it is needed. And if possible remove the clk structure and hit the clk on in driver probe so we don't waste memory modeling something that never matters. Typically that can only be done if nothing references this clk as a parent or if we're willing to break the clk tree and ignore describing parents. In this case it's a branch so probably nothing else is under it so we can just turn it on during probe and stop caring. > + .ops = &clk_branch2_ops, > + }, > + }, > +}; > + > +static struct clk_branch gcc_qdss_cfg_ahb_clk = { > + .halt_reg = 0x29008, > + .clkr = { > + .enable_reg = 0x29008, > + .enable_mask = BIT(0), > + .hw.init = &(struct clk_init_data){ > + .name = "gcc_qdss_cfg_ahb_clk", > + .parent_names = (const char *[]){ > + "pcnoc_clk_src" > + }, > + .num_parents = 1, > + .flags = CLK_SET_RATE_PARENT, > + .ops = &clk_branch2_
Re: [PATCH v3 00/15] Tegra XHCI controller ELPG support
Yes, it's safe to apply "clk: tegra: Don't enable PLLE HW sequencer at init" before the others have applied. Disabling PLLE hardware power sequencer will not cause any functionality problem to XUSB/PCIE/SATA. The only thing changed is PLLE won't be powered off by hardware when all clients are in low power state, i.e., software has to explicitly power off PLLE. Thanks for review. JC On 9/28/20 8:54 PM, Thierry Reding wrote: > On Wed, Sep 09, 2020 at 04:10:26PM +0800, JC Kuo wrote: >> Tegra XHCI controler can be placed in ELPG (Engine Level PowerGated) >> state for power saving when all of the connected USB devices are in >> suspended state. This patch series includes clk, phy and pmc changes >> that are required for properly place controller in ELPG and bring >> controller out of ELPG. >> >> JC Kuo (15): >> clk: tegra: Add PLLE HW power sequencer control >> clk: tegra: Don't enable PLLE HW sequencer at init > > Is it safe to apply this second patch before the others have applied? > Since we now need to explicitly enable the HW sequencer, it won't be > enabled before the corresponding patch does that. So applying patch 2 > before the others sounds like it would break existing users of the HW > sequencer. > > Thierry >
RE: [PATCH] rtw88: fix fw_fifo_addr check
> On Sun, Oct 11, 2020 at 08:54:38AM -0700, t...@redhat.com wrote: > > From: Tom Rix > > > > The clang build reports this warning > > > > fw.c:1485:21: warning: address of array 'rtwdev->chip->fw_fifo_addr' > > will always evaluate to 'true' > > if (!rtwdev->chip->fw_fifo_addr) { > > > > fw_fifo_addr is an array in rtw_chip_info so it is always nonzero. A > > better check is if the first element of the array is nonzero. In the > > cases where fw_fifo_addr is initialized by rtw88b and rtw88c, the > > first array element is 0x780. > > > > Signed-off-by: Tom Rix > > Reviewed-by: Nathan Chancellor > Thanks for your fix, Acked-by: Tzu-En Huang > > --- > > drivers/net/wireless/realtek/rtw88/fw.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/drivers/net/wireless/realtek/rtw88/fw.c > > b/drivers/net/wireless/realtek/rtw88/fw.c > > index 042015bc8055..b2fd87834f23 100644 > > --- a/drivers/net/wireless/realtek/rtw88/fw.c > > +++ b/drivers/net/wireless/realtek/rtw88/fw.c > > @@ -1482,7 +1482,7 @@ static bool rtw_fw_dump_check_size(struct > > rtw_dev *rtwdev, int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 > fifo_sel, u32 addr, u32 size, > > u32 *buffer) > > { > > - if (!rtwdev->chip->fw_fifo_addr) { > > + if (!rtwdev->chip->fw_fifo_addr[0]) { > > rtw_dbg(rtwdev, RTW_DBG_FW, "chip not support dump fw fifo\n"); > > return -ENOTSUPP; > > } > > -- > > 2.18.1 > > > > --Please consider the environment before printing this e-mail.
[PATCH v3] Documentation: Chinese translation of Documentation/arm64/hugetlbpage.rst
This is a Chinese translated version of Documentation/arm64/hugetlbpage.rst Signed-off-by: Bailu Lin --- Changes in v3: - Modify a translation as Alex sugguested. Changes in v2: - Fix Sphinx 2.4.4's waring by increasing underline' size. --- Documentation/arm64/hugetlbpage.rst | 2 + .../translations/zh_CN/arm64/hugetlbpage.rst | 45 +++ .../translations/zh_CN/arm64/index.rst| 1 + 3 files changed, 48 insertions(+) create mode 100644 Documentation/translations/zh_CN/arm64/hugetlbpage.rst diff --git a/Documentation/arm64/hugetlbpage.rst b/Documentation/arm64/hugetlbpage.rst index b44f939e5210..a110124c11e3 100644 --- a/Documentation/arm64/hugetlbpage.rst +++ b/Documentation/arm64/hugetlbpage.rst @@ -1,3 +1,5 @@ +.. _hugetlbpage_index: + HugeTLBpage on ARM64 diff --git a/Documentation/translations/zh_CN/arm64/hugetlbpage.rst b/Documentation/translations/zh_CN/arm64/hugetlbpage.rst new file mode 100644 index ..13304d269d0b --- /dev/null +++ b/Documentation/translations/zh_CN/arm64/hugetlbpage.rst @@ -0,0 +1,45 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/arm64/hugetlbpage.rst ` + +Translator: Bailu Lin + += +ARM64中的 HugeTLBpage += + +大页依靠有效利用 TLBs 来提高地址翻译的性能。这取决于以下 +两点 - + + - 大页的大小 + - TLBs 支持的条目大小 + +ARM64 接口支持2种大页方式。 + +1) pud/pmd 级别的块映射 +--- + +这是常规大页,他们的 pmd 或 pud 页面表条目指向一个内存块。 +不管 TLB 中支持的条目大小如何,块映射可以减少翻译大页地址 +所需遍历的页表深度。 + +2) 使用连续位 +- + +架构中转换页表条目(D4.5.3, ARM DDI 0487C.a)中提供一个连续 +位告诉 MMU 这个条目是一个连续条目集的一员,它可以被缓存在单 +个 TLB 条目中。 + +在 Linux 中连续位用来增加 pmd 和 pte(最后一级)级别映射的大 +小。受支持的连续页表条目数量因页面大小和页表级别而异。 + + +支持以下大页尺寸配置 - + + == === + - CONT PTEPMDCONT PMDPUD + == === + 4K: 64K 2M 32M 1G + 16K: 2M32M 1G + 64K: 2M 512M 16G + == === diff --git a/Documentation/translations/zh_CN/arm64/index.rst b/Documentation/translations/zh_CN/arm64/index.rst index 646ed1f7aea3..e31a6090384d 100644 --- a/Documentation/translations/zh_CN/arm64/index.rst +++ b/Documentation/translations/zh_CN/arm64/index.rst @@ -14,3 +14,4 @@ ARM64 架构 :maxdepth: 2 amu +hugetlbpage -- 2.20.1